_form.html.erb 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. <%= form_for(@transfer, html: { class: "form-horizontal", id: "transfer_form" }) do |f| %>
  2. <div class="portlet-body form">
  3. <% if @transfer.errors.any? %>
  4. <div class="alert alert-danger">
  5. <strong>Tiene <%= pluralize(@transfer.errors.count, "error") %> no se puede guardar el traspaso</strong><br>
  6. <ul>
  7. <% @transfer.errors.values.each do |message| %>
  8. <li><%= message.first.to_s %></li>
  9. <% end %>
  10. </ul>
  11. </div>
  12. <% end %>
  13. <div class="row">
  14. <!-- boton para resetear datos -->
  15. <div class="col-md-offset-10 col-md-2">
  16. <button id="reset_pre_transfers" type="button" class="btn btn-warning" <%= 'disabled' if @pre_transfers.blank? %> onclick="deletePreTransfers()">Restaurar traspaso</button>
  17. </div>
  18. <div class="col-md-7">
  19. <!-- fecha -->
  20. <div class="form-group">
  21. <%= f.label :transfer_date, "Fecha", {:class=>"col-md-3 control-label"} do %> Fecha
  22. <span class="required">*</span>
  23. <% end %>
  24. <%= f.hidden_field :transfer_date, {:value=>Date.today} %>
  25. <div class="col-sm-6" style="padding-left:0px;padding-right:0px;">
  26. <div class='input-group date' id='datetimepicker1'>
  27. <input type='text' class="form-control" disabled/>
  28. <span class="input-group-addon">
  29. <span class="glyphicon glyphicon-calendar"></span>
  30. </span>
  31. </div>
  32. </div>
  33. </div>
  34. <!-- origen -->
  35. <div class="form-group">
  36. <%= f.label :origin_id, "Punto de venta", {:class=>"col-md-3 control-label"} do %>Origen
  37. <span class="required">*</span>
  38. <% end %>
  39. <div class="input-group col-md-6 select2-bootstrap-prepend">
  40. <%= f.select :origin_id, grouped_options_for_select([
  41. ['Puntos de venta', Pointsale.activos.collect { |p| [ p.name, ('P-' + p.id.to_s) ] }],
  42. ['Almacenes', Warehouse.activos.collect { |w| [ w.name, ('W-' + w.id.to_s)] }]], :selected => @origin_id), {:prompt => "Seleccione"}, { :class => 'form-control select2', :disabled => @disable_origin} %>
  43. <%= f.hidden_field :origin_id, :value => @origin_id, :id => 'origin_id' %>
  44. </div>
  45. </div>
  46. <!-- destino -->
  47. <div class= "form-group">
  48. <%= f.label :destiny_id, "Punto de venta", {:class=>"col-md-3 control-label"} do %>Destino
  49. <span class="required">*</span>
  50. <% end %>
  51. <div class="input-group col-md-6 select2-bootstrap-prepend">
  52. <%= f.select :destiny_id, grouped_options_for_select([
  53. ['Puntos de venta', @destiny_pointsales.collect { |p| [ p.name, ('P-' + p.id.to_s)] }],
  54. ['Almacenes', Warehouse.activos.collect { |w| [ w.name, ('W-' + w.id.to_s)] }]], :selected => @destiny_id), {:prompt => "Seleccione"}, { :class => 'form-control select2', :disabled => @disable_destiny} %>
  55. <%= f.hidden_field :destiny_id, :value => @destiny_id, :id => 'destiny_id' %>
  56. </div>
  57. </div>
  58. </div>
  59. </div>
  60. <!-- agregar productos -->
  61. <h4 class="form-section">Producto(s) a traspasar</h4>
  62. <div class="row">
  63. <div class='col-md-12'>
  64. <div class="form-group">
  65. <label class="col-md-2 control-label" for="typeahead"> Producto
  66. <span class="required">*</span>
  67. </label>
  68. <div class="col-md-4">
  69. <input class="form-control" type="text" id="typeahead">
  70. </div>
  71. <button id="products_new" disabled class="btn btn-success" type="button" onclick="addRow()"> Agregar <i class="fa fa-plus"></i> </button>
  72. </div>
  73. </div>
  74. </div>
  75. <!-- lista de productos -->
  76. <h4 class="form-section"> </h4>
  77. <div class="portlet-body">
  78. <table class="table table-striped table-bordered table-hover tableadvanced" id="products_table">
  79. <thead>
  80. <tr>
  81. <th width="5%">#</th>
  82. <th width="20%">Imagen</th>
  83. <th width="20%">SKU</th>
  84. <th width="15%">Producto</th>
  85. <th>Stock actual</th>
  86. <th width="20%">Cantidad</th>
  87. <th width="10%">Acciones</th>
  88. </tr>
  89. </thead>
  90. <tbody>
  91. <%= render @pre_transfers %>
  92. </tbody>
  93. </table>
  94. </div>
  95. <!-- acciones del form -->
  96. <div class="form-actions">
  97. <div class="row">
  98. <div class="col-md-9">
  99. <!-- < %= f.submit 'Guardar', { class: "btn green", disabled: (@pre_transfers.present? ? false : true), id: "save_transfer" } %> -->
  100. <button type="button" class="btn green" onclick="addTransfer()" id="save_transfer" <%= 'disabled' if @pre_transfers.blank? %>>Guardar</button>
  101. <%= link_to 'Cancelar', transfers_path(filter: @filter, current_page: @current_page), { class: "btn default" } %>
  102. </div>
  103. </div>
  104. </div>
  105. </div>
  106. <% end %>
  107. <script type="text/javascript">
  108. var selectedProduct;
  109. var timeout = null;
  110. function addTransfer() {
  111. var origin = $('#origin_id').val();
  112. var destiny = $('#destiny_id').val();
  113. if((origin && destiny) && (origin != destiny)) {
  114. $("#transfer_form").submit();
  115. } else {
  116. toastr["error"]("Falta seleccionar datos del formulario, o el origen y el destino son los mismos.");
  117. }
  118. }
  119. $(document).on("page:change", function() {
  120. App.init();
  121. enumeratePreTransfers();
  122. $('#datetimepicker1').datetimepicker({
  123. icons: {
  124. date: "fa fa-calendar"
  125. },
  126. format: "DD/MM/YYYY",
  127. defaultDate: new Date()
  128. });
  129. });
  130. var bloodhound = new Bloodhound({
  131. datumTokenizer: function (d) {
  132. return Bloodhound.tokenizers.whitespace(d.value);
  133. },
  134. queryTokenizer: Bloodhound.tokenizers.whitespace,
  135. remote: {
  136. url: "/find_from_stock_by_pointsale?pointsale_id=ID&query=%QUERY",
  137. wildcard: '%QUERY',
  138. replace: function(url, uriEncodedQuery) {
  139. origin = $('#origin_id').val();
  140. return url.replace('ID', origin).replace('%QUERY', uriEncodedQuery)
  141. }
  142. }
  143. });
  144. bloodhound.initialize();
  145. $('#typeahead').typeahead(
  146. {
  147. minLength: 3
  148. },
  149. {
  150. displayKey: 'name',
  151. source: bloodhound.ttAdapter(),
  152. limit: Infinity,
  153. templates: {
  154. empty: [
  155. '<div class="empty-message">',
  156. 'No se encontró ningun producto. Favor de verificar',
  157. '</div>'
  158. ].join('\n'),
  159. suggestion: Handlebars.compile(
  160. '<div class="media">' +
  161. '<div class="pull-left">' +
  162. '<div class="media-object">' +
  163. '<img src="{{small_img}}" width="50" height="50"/>' +
  164. '</div>' +
  165. '</div>' +
  166. '<div class="media-body">' +
  167. '<h4 class="media-heading"><strong>{{sku}}</strong> | {{name}}</h4>' +
  168. '<p>{{barcode}}</p>' +
  169. '<p>{{description}}</p>' +
  170. '<p>{{display_attributes}}</p>' +
  171. '</div>' +
  172. '</div>')
  173. }
  174. });
  175. $('body').barcodeListener().on('barcode.valid', function(e, code) {
  176. findProductByBarcode(code);
  177. });
  178. $('#transfer_destiny_id').on('change', function() {
  179. $('#destiny_id').val($(this).val());
  180. });
  181. $('#transfer_origin_id').on('change', function() {
  182. $('#origin_id').val($(this).val());
  183. });
  184. $('#typeahead').bind('typeahead:selected', function(event, datum, name) {
  185. selectedProduct = datum;
  186. $('#products_new').attr('disabled', false);
  187. });
  188. function addRow() {
  189. if(selectedProduct) {
  190. $('#pre_transfer_origin_id').val($('#origin_id').val());
  191. $('#pre_transfer_destiny_id').val($('#transfer_destiny_id').val());
  192. $('#pre_transfer_product_id').val(selectedProduct.id);
  193. $('#pre_transfer_quantity').val(1);
  194. $('#new_pre_transfer').submit();
  195. $('#typeahead').typeahead('val','');
  196. $('#products_new').attr('disabled', true);
  197. }
  198. }
  199. function deleteRow(input) {
  200. var table = $('#products_table').DataTable();
  201. var idText = input.closest('tr').attr('id');
  202. var preTransferId = idText.substring(idText.lastIndexOf('_') + 1, idText.length);
  203. $.ajax({
  204. type: "DELETE",
  205. url: "/pre_transfers/" + preTransferId,
  206. dataType: "json",
  207. data: "",
  208. success: function(xhr, status, error) {
  209. table.row(input.closest('tr')).remove().draw();
  210. }
  211. });
  212. }
  213. function enumeratePreTransfers() {
  214. if($('#reset_pre_transfers').prop("disabled") == false) {
  215. var table = $('#products_table').dataTable();
  216. var counter = 1;
  217. $('#products_table tbody tr').each(function() {
  218. $(this).find('td:eq(0)').html($(this).find('td:eq(0)').html().replace('#', counter));
  219. counter++;
  220. });
  221. }
  222. }
  223. function deletePreTransfers() {
  224. $.ajax({
  225. type: "get",
  226. url: '/delete_pre_transfers',
  227. dataType: 'json',
  228. success: function(xhr, status, error){
  229. $('#products_table').dataTable().fnClearTable();
  230. $("#transfer_destiny_id").select2().select2("val", null);
  231. <% if current_user.usertype == 'A' %>
  232. $("#transfer_origin_id").attr('disabled', false);
  233. $("#transfer_origin_id").select2().select2("val", null);
  234. <% end %>
  235. $("#transfer_destiny_id").attr('disabled', false);
  236. $("#reset_pre_transfers").attr('disabled', true);
  237. }
  238. });
  239. }
  240. function updateQuantity(input) {
  241. if(input.val() > 0) {
  242. clearTimeout(timeout);
  243. timeout = setTimeout(function () {
  244. var idText = input.closest('tr').attr('id');
  245. var preTransferId = idText.substring(idText.lastIndexOf('_') + 1, idText.length);
  246. $.ajax({
  247. type: "PUT",
  248. url: "/pre_transfers/" + preTransferId,
  249. dataType: "json",
  250. data: {pre_transfer: {quantity: input.val()}},
  251. success: function(xhr, status, error) {
  252. $("#save_transfer").attr("disabled", false);
  253. },
  254. statusCode: {
  255. 422: function() {
  256. $("#save_transfer").attr("disabled", true);
  257. toastr["error"]("Error, El stock es insuficiente.");
  258. }
  259. }
  260. });
  261. }, 700);
  262. } else {
  263. $("#save_transfer").attr("disabled", true);
  264. toastr["error"]("La cantidad debe ser mayor a 0");
  265. }
  266. }
  267. function findProductByBarcode(barcode) {
  268. var origin = $('#origin_id').val();
  269. var destiny = $('#destiny_id').val();
  270. if((origin && destiny) && (origin != destiny)) {
  271. $.ajax({
  272. type: "get",
  273. url: '/add_pre_transfer_by_barcode/' + barcode + "/" + origin + "/" + destiny,
  274. dataType: 'script',
  275. success: function(data) {
  276. },
  277. });
  278. } else {
  279. toastr["error"]("Falta seleccionar datos del formulario, o el origen y el destino son los mismos.");
  280. }
  281. }
  282. </script>