_form.html.erb 24 KB

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