_form.html.erb 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. <%= form_for(@sale, :remote => true, :html => {:class=>"form-horizontal", :id=> "sale_form"}) do |f| %>
  2. <div class="portlet-body form">
  3. <!-- este error explanation se usa para mostrar errores de presales e inventarios -->
  4. <div id="error_explanation"></div>
  5. <!-- este error explanation es cuando falla alguna validacion de la venta en sí -->
  6. <div class="alert alert-danger hidden" id="error_explanation_for_sale"></div>
  7. <div class="row">
  8. <!-- boton para resetear datos -->
  9. <div class="col-md-offset-10 col-md-2">
  10. <button id="reset_pre_sales" type="button" class="btn btn-warning" <%= @disabled_button ? 'disabled' : '' %> onclick="deletePreSales()">Restaurar venta</button>
  11. </div>
  12. <div class="col-md-8">
  13. <h4 class="form-section"> Datos generales</h4>
  14. <!-- purchase code -->
  15. <div class="form-group">
  16. <%= f.label :sale_code, {:class=>"col-md-3 control-label"} do %> Código de compra
  17. <span class="required">*</span>
  18. <% end %>
  19. <div class="col-md-6 input-group">
  20. <span class="input-group-addon"><i class="fa fa-barcode"></i></span>
  21. <%= f.text_field :sale_code, {:class=>"form-control", :readonly => true} %>
  22. </div>
  23. </div>
  24. <!-- fecha -->
  25. <div class="form-group">
  26. <%= hidden_field_tag :tax_percent, @pos_config.tax_percent %>
  27. <%= f.label :date_sale, "Fecha", {:class=>"col-md-3 control-label"} do %> Fecha
  28. <span class="required">*</span>
  29. <% end %>
  30. <%= f.hidden_field :date_sale, {:value=>Date.today} %>
  31. <div class="col-sm-6" style="padding-left:0px;padding-right:0px;">
  32. <div class='input-group date' id='datetimepicker1'>
  33. <span class="input-group-addon">
  34. <span class="glyphicon glyphicon-calendar"></span>
  35. </span>
  36. <input type='text' class="form-control" disabled/>
  37. </div>
  38. </div>
  39. </div>
  40. <!-- open cash register -->
  41. <% if current_user.usertype == 'C' %>
  42. <%= f.hidden_field :open_cash_register_id, :value => @open_cash_register.id %>
  43. <% end %>
  44. <% if current_user.usertype == 'G' %>
  45. <div class="form-group">
  46. <%= f.label :open_cash_register_id, "Caja registradora", {:class=>"col-md-3 control-label"} do %> Caja registradora
  47. <span class="required">*</span>
  48. <% end %>
  49. <div class="input-group col-md-6 select2-bootstrap-prepend">
  50. <%= f.select :open_cash_register_id, Pointsale.find(current_user.pointsale_id).open_cash_registers.abiertas.map{|o| [o.cash_register.name, o.id]}, {:prompt => "Seleccione"}, { :class => 'form-control select2', :disabled => @disabled_select } %>
  51. <%= f.hidden_field :open_cash_register_id, {:id => 'open_cash'} %>
  52. </div>
  53. </div>
  54. <% end %>
  55. <!-- cliente -->
  56. <div class="form-group">
  57. <%= f.label :customer_id, "Cliente", {:class=>"col-md-3 control-label"} do %> Cliente
  58. <span class="required">*</span>
  59. <% end %>
  60. <div class="input-group col-md-6 select2-bootstrap-prepend" style="float:left">
  61. <%= f.collection_select :customer_id, Customer.vigentes, :id, :nick_name, {:prompt => "Seleccione", :selected => @sale.customer_id.present? ? @sale.customer_id : @general_public_id}, {:class => "form-control select2", :disabled => @disabled_select} %>
  62. <%= f.hidden_field :customer_id, :value => @sale.customer_id.present? ? @sale.customer_id : @general_public_id, :id => 'customer' %>
  63. </div>
  64. <div class="col-md-2">
  65. <% if @pre_sales.count == 0 %>
  66. <%= link_to new_customer_path, :remote => true, :class=>"btn btn-success", :id => :customer_remote do %>
  67. <i class="fa fa-plus"></i>
  68. <% end %>
  69. <% end %>
  70. </div>
  71. </div>
  72. <!-- tipo de venta -->
  73. <div class="form-group">
  74. <%= f.label :saletype, {:class=>"col-md-3 control-label"} do %> ¿Tipo de venta?
  75. <span class="required">*</span><% end %>
  76. <div class="btn-group col-md-6" data-toggle="buttons" style="padding-left:0px;padding-right:0px">
  77. <label class="col-md-4 btn default <%= @sale.saletype == 'cash' ? 'active' : (@enable_radios ? '' : 'disabled') %>">
  78. <%= radio_button_tag 'types', "cash", (@sale.saletype == 'cash'), class: "toggle" %> Contado
  79. </label>
  80. <label class="col-md-4 btn default <%= @sale.saletype == 'credit' ? 'active' : (@enable_radios ? '' : 'disabled') %>">
  81. <%= radio_button_tag 'types', "credit", (@sale.saletype == 'credit'), class: "toggle" %> Crédito
  82. </label>
  83. <label class="col-md-4 btn default <%= @sale.saletype == 'reserved' ? 'active' : (@enable_radios ? '' : 'disabled') %>">
  84. <%= radio_button_tag 'types', "reserved", (@sale.saletype == 'reserved'), class: "toggle" %> Apartado
  85. </label>
  86. <%= f.hidden_field :saletype %>
  87. </div>
  88. </div>
  89. <!-- vale -->
  90. <div class="form-group hidden" id="credit_note_div">
  91. <%= f.label :credit_note, {:class=>"col-md-3 control-label"} do %> Folio de vale <% end %>
  92. <div class="col-md-6 input-group">
  93. <span class="input-group-addon"><i class="fa fa-ticket"></i></span>
  94. <%= f.text_field :credit_note, {:class=>"form-control"} %>
  95. </div>
  96. </div>
  97. <!-- vendedor -->
  98. <div class="form-group">
  99. <%= f.label :seller_id, "Vendedor", {:class=>"col-md-3 control-label"} do %> Vendedor
  100. <span class="required">*</span>
  101. <% end %>
  102. <div class="input-group col-md-6 select2-bootstrap-prepend">
  103. <%= f.collection_select :seller_id, Seller.where(:pointsale_id => current_user.pointsale_id, :status => '1'), :id, :full_name, {:prompt => "Seleccione",
  104. :selected => @seller.blank? ? '' : @seller_id.to_i}, {:class => "form-control select2"} %>
  105. </div>
  106. </div>
  107. </div>
  108. <div class="col-md-4 hidden" id="customer_info">
  109. <h4 class="form-section"> Datos del cliente</h4>
  110. <div class="panel panel-info">
  111. <!-- Default panel contents -->
  112. <div class="panel-heading">
  113. <h3 class="panel-title" id="customer_name"></h3>
  114. </div>
  115. <!-- List group -->
  116. <ul class="list-group">
  117. <li class="list-group-item"> ¿Tiene crédito?
  118. <span class="badge badge-info badge-roundless" id="has_credit"></span>
  119. </li>
  120. <li class="list-group-item"> Adeudo del cliente
  121. <span class="badge badge-info badge-roundless" id="customer_debiting"></span>
  122. </li>
  123. <li class="list-group-item"> Límite de crédito
  124. <span class="badge badge-info badge-roundless" id="credit_limit"></span>
  125. </li>
  126. <li class="list-group-item"> Fecha de último abono
  127. <span class="badge badge-info badge-roundless" id="last_credit_payment"></span>
  128. </li>
  129. </ul>
  130. </div>
  131. </div>
  132. </div>
  133. <!-- agregar productos -->
  134. <h4 class="form-section"> Agregar producto</h4>
  135. <div class="row">
  136. <div class="col-md-12">
  137. <div class="note note-info">
  138. <h4 class="block">¡Nota!</h4>
  139. <p> Para hacer una busqueda avanzada utiliza el siguiente formato, nombre del producto :atributo a buscar<br>
  140. ejemplo. <strong>blusa :verde</strong> (Solo se puede buscar un atributo, ya sea estilo, talla ó color).</p>
  141. </div>
  142. </div>
  143. <div class='col-md-12'>
  144. <div class="form-group">
  145. <label class="col-md-2 control-label" for="typeahead"> Producto
  146. <span class="required">*</span>
  147. </label>
  148. <div class="col-md-4">
  149. <input class="form-control" type="text" id="typeahead" data-option-url="/find_products_from_stock/%QUERY">
  150. </div>
  151. <button id="products_new" disabled class="btn btn-success" type="button" onclick="addRow()"> Agregar <i class="fa fa-plus"></i> </button>
  152. </div>
  153. </div>
  154. </div>
  155. <!-- lista de productos -->
  156. <h4 class="form-section"> Lista de productos</h4>
  157. <div class="portlet-body">
  158. <table class="table table-striped table-bordered table-hover tableadvanced" id="products_table">
  159. <thead>
  160. <tr>
  161. <th>#</th>
  162. <th>SKU</th>
  163. <th>Imagen</th>
  164. <th>Producto</th>
  165. <th>Cantidad</th>
  166. <th>Precio unitario</th>
  167. <th>IVA</th>
  168. <th>Descuento</th>
  169. <th>Importe</th>
  170. <th width="15%">Acciones</th>
  171. </tr>
  172. </thead>
  173. <tbody>
  174. <%= render @pre_sales %>
  175. </tbody>
  176. </table>
  177. </div>
  178. <!-- totales -->
  179. <div class="row">
  180. <div class="col-md-offset-8 col-md-4">
  181. <div class="well">
  182. <div class="row static-info align-reverse">
  183. <div class="col-md-6 name"> Sub Total: </div>
  184. <div class="col-md-6 value ">
  185. <div class="input-group">
  186. <span class="input-group-addon">$ </span>
  187. <%= f.text_field :amount, {:class=>"form-control sub_total", :readonly => true, :id => "amount"} %>
  188. </div>
  189. </div>
  190. </div>
  191. <div class="row static-info align-reverse">
  192. <div class="col-md-6 name"> Descuento: </div>
  193. <div class="col-md-6 value ">
  194. <div class="input-group">
  195. <span class="input-group-addon">$ </span>
  196. <%= f.text_field :discount, {:class=>"form-control sub_total", :readonly => true, :id => "discount"} %>
  197. </div>
  198. </div>
  199. </div>
  200. <div class="row static-info align-reverse">
  201. <div class="col-md-6 name"> IVA: </div>
  202. <div class="col-md-6 value ">
  203. <div class="input-group">
  204. <span class="input-group-addon">$ </span>
  205. <%= f.text_field :tax, {:class=>"form-control descto", :readonly => true, :id => "tax"} %>
  206. </div>
  207. </div>
  208. </div>
  209. <div class="row static-info align-reverse">
  210. <div class="col-md-6 name"> Total: </div>
  211. <div class="col-md-6 value ">
  212. <div class="input-group">
  213. <span class="input-group-addon">$ </span>
  214. <%= f.text_field :total, {:class=>"form-control descto", :readonly => true, :id => "total"} %>
  215. </div>
  216. </div>
  217. </div>
  218. </div>
  219. </div>
  220. </div>
  221. <!-- acciones del form -->
  222. <div class="form-actions">
  223. <div class="row">
  224. <div class="col-md-9">
  225. <button type="button" class="btn green" onclick="addSale()" id="save_sale">Guardar venta</button>
  226. <%= link_to 'Cancelar', sales_path(:filter => @filter, :current_page => @current_page), {:class=>"btn default"} %>
  227. </div>
  228. </div>
  229. </div>
  230. </div>
  231. <% end %>
  232. <script type="text/javascript">
  233. var selectedProduct;
  234. var timeout = null;
  235. $(document).on("page:change", function() {
  236. App.init();
  237. calculateTotals();
  238. fillCustomerInfo();
  239. enumeratePreSales();
  240. generateSaleCode();
  241. // si es publico en general, desactivar venta a credito y apartado
  242. if ($('#sale_customer_id').val() == '<%= @general_public_id %>') {
  243. $('#types_credit').attr('disabled', true);
  244. $('#types_credit').closest('label').addClass('disabled');
  245. $('#types_reserved').attr('disabled', true);
  246. $('#types_reserved').closest('label').addClass('disabled');
  247. }
  248. $('#datetimepicker1').datetimepicker({
  249. icons: {
  250. date: "fa fa-calendar"
  251. },
  252. format: "DD/MM/YYYY",
  253. defaultDate: new Date()
  254. });
  255. $("#new_pre_sale").bind('ajax:complete', function() {
  256. calculateTotals();
  257. });
  258. $('#sale_customer_id').on('change', function() {
  259. $(this).attr('disabled', true);
  260. $('#customer').val($(this).val());
  261. //bloquear boton para agregar nuevo cliente ya que se selecciono o agrego uno
  262. $('#customer_remote').removeAttr("href");
  263. $('#customer_remote').attr("disabled", true);
  264. // activar apartado y el credito se activa dependiendo si tiene o no,
  265. // en la funcion fillCustomer
  266. if ($('#sale_customer_id').val() != '<%= @general_public_id %>') {
  267. $('#types_reserved').attr('disabled', false);
  268. $('#types_reserved').closest('label').removeClass('disabled');
  269. }
  270. fillCustomerInfo();
  271. });
  272. $('#sale_open_cash_register_id').on('change', function() {
  273. $(this).attr('disabled', true);
  274. $('#open_cash').val($(this).val());
  275. generateSaleCode();
  276. });
  277. $('input:radio[name=types]').change(function() {
  278. if (!$(this).closest('label').hasClass('disabled')) {
  279. <% if @pre_sales.count == 0 %>
  280. if (!$(this).closest('label').hasClass('disabled')) {
  281. $('#sale_saletype').val($(this).val());
  282. } else {
  283. var type = $('#sale_saletype').val();
  284. $(":radio[value=" + type + "]").closest('label').addClass('active');
  285. }
  286. <% else %>
  287. var type = '<%= @sale.saletype %>';
  288. $(":radio[value=" + type + "]").closest('label').addClass('active');
  289. <% end %>
  290. //Si es tipo crédito, aparecer input de vale
  291. if ($(this).val() == 'credit') {
  292. $('#credit_note_div').removeClass('hidden');
  293. } else {
  294. $('#credit_note_div').addClass('hidden');
  295. $('#sale_credit_note').val('');
  296. }
  297. }
  298. });
  299. $(document).on("keydown", function (e) {
  300. if (window.location.pathname == "/sales/new") {
  301. if (e.which === 8 && !$(e.target).is("input, textarea")) {
  302. e.preventDefault();
  303. }
  304. }
  305. });
  306. });
  307. $('body').barcodeListener().on('barcode.valid', function(e, code) {
  308. findProductByBarcode(code);
  309. });
  310. // initialize bloodhound engine
  311. var bloodhound = new Bloodhound({
  312. datumTokenizer: function (d) {
  313. return Bloodhound.tokenizers.whitespace(d.value);
  314. },
  315. queryTokenizer: Bloodhound.tokenizers.whitespace,
  316. remote: {
  317. url: $('#typeahead').data('option-url'),
  318. wildcard: '%QUERY'
  319. }
  320. });
  321. bloodhound.initialize();
  322. $('#typeahead').typeahead(
  323. {
  324. minLength: 3
  325. },
  326. {
  327. displayKey: 'name',
  328. source: bloodhound.ttAdapter(),
  329. limit: Infinity,
  330. templates: {
  331. empty: [
  332. '<div class="empty-message">',
  333. 'No se encontró ningun producto. Favor de verificar',
  334. '</div>'
  335. ].join('\n'),
  336. suggestion: Handlebars.compile(
  337. '<div class="media">' +
  338. '<div class="pull-left">' +
  339. '<div class="media-object">' +
  340. '<img src="{{small_img}}" width="50" height="50"/>' +
  341. '</div>' +
  342. '</div>' +
  343. '<div class="media-body">' +
  344. '<h4 class="media-heading"><strong>{{sku}}</strong> | {{name}}</h4>' +
  345. '<p>{{barcode}}</p>' +
  346. '<p>{{description}}</p>' +
  347. '<p>{{display_attributes}}</p>' +
  348. '</div>' +
  349. '</div>')
  350. }
  351. });
  352. // this is the event that is fired when a user clicks on a suggestion
  353. $('#typeahead').bind('typeahead:selected', function(event, datum, name) {
  354. selectedProduct = datum;
  355. var openCash = $('#sale_open_cash_register_id').val();
  356. var customer = $('#sale_customer_id').val();
  357. var saleType = $('#sale_saletype').val();
  358. var seller = $('#sale_seller_id').val();
  359. if (openCash && customer && saleType && seller ) {
  360. $('#products_new').attr('disabled', false);
  361. } else {
  362. toastr["error"]("No ha ingresado toda la informacion requerida.");
  363. }
  364. });
  365. function addRow() {
  366. if(selectedProduct) {
  367. $('#pre_sale_customer_id').val($('#sale_customer_id').val());
  368. $('#pre_sale_open_cash_register_id').val($('#sale_open_cash_register_id').val());
  369. $('#pre_sale_sale_type').val($('#sale_saletype').val());
  370. $('#pre_sale_product_id').val(selectedProduct.id);
  371. $('#pre_sale_quantity').val(1);
  372. $('#new_pre_sale').submit();
  373. $('#typeahead').typeahead('val','');
  374. $('#products_new').attr('disabled', true);
  375. }
  376. }
  377. function deleteRow(input) {
  378. var table = $('#products_table').DataTable();
  379. var idText = input.closest('tr').attr('id');
  380. var preSaleId = idText.substring(idText.lastIndexOf('_') + 1, idText.length);
  381. $.ajax({
  382. type: "DELETE",
  383. url: "/pre_sales/" + preSaleId,
  384. dataType: "json",
  385. data: "",
  386. success: function(xhr, status, error) {
  387. table.row(input.closest('tr')).remove().draw();
  388. calculateTotals();
  389. }
  390. });
  391. }
  392. function calculatePrice(input) {
  393. if(input.val()) {
  394. clearTimeout(timeout);
  395. timeout = setTimeout(function () {
  396. tax = 0;
  397. quantity = parseInt(input.val());
  398. var idText = input.closest('tr').attr('id');
  399. var preSaleId = idText.substring(idText.lastIndexOf('_') + 1, idText.length);
  400. $('#save_sale').attr('disabled', true);
  401. $.ajax({
  402. type: "PUT",
  403. url: "/pre_sales/" + preSaleId,
  404. dataType: "json",
  405. data: {pre_sale: {quantity: input.val()}},
  406. success: function(xhr, status, error) {
  407. input.closest('tr').find('td:eq(6)').text(Math.round(xhr.tax * 100) / 100);
  408. input.closest('tr').find('td:eq(7)').text(Math.round(xhr.discount * 100) / 100);
  409. input.closest('tr').find('td:eq(8)').text(Math.round(xhr.total * 100) / 100);
  410. calculateTotals();
  411. $('#save_sale').attr('disabled', false);
  412. },
  413. error: function (xhr, status, errorThrown) {
  414. toastr["error"](xhr.responseText.substr(3, (xhr.responseText.length -6)));
  415. }
  416. });
  417. }, 500);
  418. }
  419. }
  420. function calculateTotals() {
  421. var amount = 0;
  422. var discount = 0;
  423. var tax = 0;
  424. var total = 0;
  425. if($('#products_table').dataTable().fnGetData().length > 0) {
  426. $('#products_table tbody tr').each(function() {
  427. quantity = parseFloat(($(this).find('td:nth-child(5) input').val()));
  428. price = parseFloat($(this).find('td:nth-child(6)').text());
  429. amount+= (quantity * price);
  430. });
  431. }
  432. $('#products_table tbody tr td:nth-child(7)').each(function() {
  433. tax+= parseFloat($(this).text());
  434. });
  435. $('#products_table tbody tr td:nth-child(8)').each(function() {
  436. discount+= parseFloat($(this).text());
  437. });
  438. total = (amount - discount) + tax;
  439. $('#tax').val(Math.round(tax * 100) / 100);
  440. $('#discount').val(Math.round(discount * 100) / 100);
  441. $('#amount').val(Math.round(amount * 100) / 100);
  442. $('#total').val(Math.round(total * 100) / 100);
  443. }
  444. function deletePreSales() {
  445. $.ajax({
  446. type: "get",
  447. url: '/delete_pre_sales',
  448. dataType: 'json',
  449. success: function(xhr, status, error) {
  450. location.reload();
  451. }
  452. });
  453. }
  454. function addSale() {
  455. var $form = $('#sale_form');
  456. var table = $('#products_table').dataTable();
  457. if ($form[0].checkValidity()) {
  458. if(table.fnGetData().length > 0) {
  459. $('#sale_form').submit();
  460. } else {
  461. toastr["error"]("Error, Se debe agregar al menos un producto.");
  462. }
  463. } else {
  464. toastr["error"]("La cantidad de los productos debe de ser mayor o igual a 1.");
  465. }
  466. }
  467. function fillCustomerInfo() {
  468. var customerId = $('#customer').val();
  469. var public_customer = "<%= @general_public_id %>";
  470. if(customerId && customerId != public_customer) {
  471. $.ajax({
  472. type: "get",
  473. url: '/customers/' + customerId + ".json",
  474. dataType: 'json',
  475. success: function(data) {
  476. if(data.credit) {
  477. $('#customer_name').text(data.nick_name);
  478. $('#has_credit').text(data.credit ? 'SI' : 'NO');
  479. // $('#customer_debiting').text(formatter.format(data.customer_debiting.customer_debiting));
  480. // $('#credit_limit').text(formatter.format(data.credit_limit));
  481. $('#customer_debiting').text(accounting.formatMoney(data.customer_debiting.customer_debiting));
  482. $('#credit_limit').text(accounting.formatMoney(data.credit_limit));
  483. if(data.customer_payment) {
  484. $('#last_credit_payment').text(data.customer_payment.customer_payment);
  485. }
  486. $('#customer_info').removeClass('hidden');
  487. <% if @pre_sales.count == 0 %>
  488. $('#types_credit').attr('disabled', false);
  489. $('#types_credit').closest('label').removeClass('disabled');
  490. <% end %>
  491. } else {
  492. // DISABLEAR EL DE CREDITO
  493. $('#types_credit').attr('disabled', true);
  494. $('#types_credit').closest('label').addClass('disabled');
  495. }
  496. }
  497. });
  498. }
  499. }
  500. function enumeratePreSales() {
  501. if($('#reset_pre_sales').prop("disabled") == false) {
  502. var table = $('#products_table').dataTable();
  503. var counter = 1;
  504. $('#products_table tbody tr').each(function() {
  505. $(this).find('td:eq(0)').html($(this).find('td:eq(0)').html().replace('#', counter));
  506. counter++;
  507. });
  508. }
  509. }
  510. function generateSaleCode() {
  511. if($('#sale_open_cash_register_id').val()) {
  512. $.ajax({
  513. type: "get",
  514. url: '/get_next_sale_code/' + $('#sale_open_cash_register_id').val(),
  515. dataType: 'text',
  516. success: function(data) {
  517. $('#sale_sale_code').val(data);
  518. },
  519. });
  520. }
  521. }
  522. function findProductByBarcode(barcode) {
  523. var customer = $('#sale_customer_id').val();
  524. var openCash = $('#sale_open_cash_register_id').val();
  525. var saleType = $('form input[type=radio]:checked').val();
  526. var seller = $('#sale_seller_id').val();
  527. if(customer && openCash && saleType && seller) {
  528. $.ajax({
  529. type: "get",
  530. url: '/add_pre_sale_by_barcode/' + barcode + "/" + customer + "/" + openCash + "/" + saleType,
  531. dataType: 'script',
  532. success: function(data) {
  533. calculateTotals();
  534. },
  535. });
  536. } else {
  537. toastr["error"]("Falta seleccionar datos del formulario.");
  538. }
  539. }
  540. </script>