sales_controller.rb 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. class SalesController < ApplicationController
  2. ##--- Abilities
  3. load_and_authorize_resource
  4. ##--- Breadcrum_rails
  5. add_breadcrumb I18n.t("breadcrumbs." + controller_name), :sales_path
  6. add_breadcrumb "Nueva " + I18n.t("breadcrumbs." + controller_name).singularize, :new_sale_path, only: :new
  7. add_breadcrumb "Detalle de la " + I18n.t("breadcrumbs." + controller_name).singularize , :sale_path, only: :show
  8. add_breadcrumb "Editar " + I18n.t("breadcrumbs." + controller_name).singularize , :edit_sale_path, only: :edit
  9. before_action :set_sale, only: [:show, :edit, :update, :destroy]
  10. before_action :get_filters, only: [:index, :show, :edit, :new, :sales_reserved]
  11. # GET /sales
  12. # GET /sales.json
  13. def index
  14. today = Date.current
  15. thirty_day_ago = today - 30
  16. if current_user.usertype == 'A'
  17. @sales = Sale.includes(:customer, :user, :seller).where(:date_sale => thirty_day_ago..today).where('saletype != 2').order(" created_at DESC ")
  18. else
  19. @sales = Pointsale.find(current_user.pointsale_id).sales.includes(:customer, :user, :seller).where(:date_sale => thirty_day_ago..today).where('saletype != 2').order(" created_at DESC ")
  20. end
  21. end
  22. def sales_reserved
  23. beg_of_month = Date.current.beginning_of_month
  24. end_of_month = Date.current.end_of_month
  25. if current_user.usertype == 'A'
  26. @sales = Sale.where(:saletype => 2).order(" created_at DESC ")
  27. else
  28. @sales = Pointsale.find(current_user.pointsale_id).sales.where(:saletype => 2).order(" created_at DESC")
  29. end
  30. end
  31. # GET /sales/1
  32. # GET /sales/1.json
  33. def show
  34. @payments = CashRegistersMove.where(:sale_id => @sale.id, :status => 1)
  35. # saca la devolucion si es que hay.
  36. @products_return = ProductsReturn.find_by(:sale_id => @sale.id)
  37. @returned_prods_ids = Array.new
  38. @returned_prods_ids = @products_return.products_return_ins.pluck(:product_id) if @products_return.present?
  39. end
  40. # GET /sales/new
  41. def new
  42. @sale = Sale.new
  43. @sale.sales_details.new
  44. @general_public_id = Customer.find_by(:is_public => 1).id
  45. @pre_sales = PreSale.where(:user_id => current_user.id)
  46. @sale.saletype = 'cash'
  47. #se desactivan cuando tienen pre sales, para mantener la congruencia de los datos.
  48. @disabled_select = false
  49. @disabled_button = true
  50. @enable_radios = true
  51. if current_user.usertype != "G"
  52. @open_cash_register = current_user.get_open_cash_register
  53. end
  54. if @pre_sales.size > 0
  55. @sale.saletype = @pre_sales[0].sale_type
  56. @sale.customer_id = @pre_sales[0].customer_id
  57. @sale.open_cash_register_id = @pre_sales[0].open_cash_register_id
  58. @disabled_select = true
  59. @disabled_button = false
  60. @enable_radios = false
  61. end
  62. end
  63. # GET /sales/1/edit
  64. def edit
  65. end
  66. # POST /sales
  67. # POST /sales.json
  68. def create
  69. respond_to do |format|
  70. @sale = Sale.new(sale_params)
  71. @pre_sales = PreSale.where(:user_id => current_user.id)
  72. @sale.user_id = current_user.id
  73. @sale.open_cash_register_id = current_user.pointsale.get_open_cash_register.id
  74. @sale.status = :notpaid
  75. @sale.expiration_date = Date.today + @pos_config.days_cancel_reserved if @sale.reserved?
  76. @sale.audit_comment = "Venta #{@sale.sale_code} por #{@sale.total} creada."
  77. if @sale.save
  78. # agregar detalles de la venta
  79. @pre_sales.each do |pre_sale|
  80. detail = SalesDetail.new
  81. detail.product_id = pre_sale.product_id
  82. detail.unit_price = pre_sale.unit_price
  83. detail.quantity = pre_sale.quantity
  84. detail.amount = pre_sale.amount
  85. detail.tax = pre_sale.tax
  86. detail.discount = pre_sale.discount
  87. detail.total = pre_sale.total
  88. detail.special_price_id = pre_sale.special_price_id
  89. detail.status = :active
  90. @sale.sales_details << detail
  91. pre_sale.destroy
  92. # actualizar stock del producto
  93. stockProduct = AvailableProduct.find_by(:product_id => detail.product_id, :pointsale_id => @sale.get_pointsale.id)
  94. unless stockProduct.blank?
  95. if stockProduct.stock.present?
  96. stockProduct.stock = stockProduct.stock - detail.quantity
  97. stockProduct.save
  98. else
  99. errors.add(:base, "No se tiene registrado el stock de alguno de los productos, es necesario configurarlo antes de generar una venta")
  100. format.json { render json: @sale.errors.values, status: :unprocessable_entity }
  101. end
  102. # guardar en bitacora de inventario
  103. move = InventoriesMove.new
  104. move.product_id = detail.product_id
  105. move.sale_id = @sale.id
  106. move.quantity = detail.quantity
  107. move.move_type = "outgoing"
  108. move.reason = "sale"
  109. move.save
  110. end
  111. end
  112. # dependiendo el tipo de venta: contado/credito determina que hacer
  113. if @sale.cash?
  114. format.js { redirect_to new_cash_registers_move_path(:sale => @sale.id) }
  115. elsif @sale.credit?
  116. credit = Credit.new
  117. credit.customer_id = @sale.customer_id
  118. credit.pointsale_id = current_user.pointsale_id
  119. credit.sale_id = @sale.id
  120. credit.total = @sale.total
  121. credit.rest = @sale.total
  122. credit.status = "active"
  123. credit.credit_note = @sale.credit_note if @sale.credit_note.present?
  124. credit.save
  125. flash[:success] = "Venta a credito registrada al cliente: #{@sale.customer.nick_name} por $ #{@sale.total}"
  126. format.js { render 'create_credit_sale' }
  127. elsif @sale.reserved?
  128. format.js { redirect_to new_cash_registers_move_path(:sale => @sale.id) }
  129. end
  130. else
  131. format.js
  132. format.json { render json: @sale.errors, status: :unprocessable_entity }
  133. end
  134. end
  135. end
  136. # PATCH/PUT /sales/1
  137. # PATCH/PUT /sales/1.json
  138. def update
  139. respond_to do |format|
  140. if @sale.update(sale_params)
  141. format.html { redirect_to @sale, notice: 'Venta modificada.' }
  142. format.json { render :show, status: :ok, location: @sale }
  143. else
  144. format.html { render :edit }
  145. format.json { render json: @sale.errors, status: :unprocessable_entity }
  146. end
  147. end
  148. end
  149. # DELETE /sales/1
  150. # DELETE /sales/1.json
  151. def destroy
  152. respond_to do |format|
  153. @sale.audit_comment = "Venta #{@sale.sale_code} cancelada."
  154. if @sale.update_attributes(:status => :cancelled)
  155. if @sale.reserved?
  156. return_cash = params[:return_cash]
  157. if return_cash == 'true'
  158. moves = CashRegistersMove.where(:sale_id => @sale.id, :move_type => 1)
  159. if moves.present?
  160. if moves[0].open_cash_register.closed?
  161. quantity_to_return = moves.sum(:quantity)
  162. new_cash_move = CashRegistersMove.new
  163. new_cash_move.skip_received_validation = true
  164. new_cash_move.open_cash_register_id = current_user.get_open_cash_register.id
  165. new_cash_move.payment_method_id = PaymentMethod.find_by(:isCash => 1).id
  166. new_cash_move.quantity = quantity_to_return
  167. new_cash_move.move_type = :egreso
  168. new_cash_move.sale_id = @sale.id
  169. new_cash_move.concept = :sale
  170. new_cash_move.status = :active
  171. new_cash_move.save
  172. else
  173. moves.destroy_all
  174. end
  175. end
  176. end
  177. elsif @sale.cash?
  178. #checa si hay pagos de esta venta
  179. moves = CashRegistersMove.where(:sale_id => @sale.id)
  180. #si la caja sigue abierta, solo elimina los moves, si ya cortó, genera un egreso por esa cantidad
  181. if moves.present?
  182. if moves[0].open_cash_register.closed?
  183. new_cash_move = CashRegistersMove.new
  184. new_cash_move.skip_received_validation = true
  185. new_cash_move.open_cash_register_id = current_user.pointsale.get_open_cash_register.id
  186. new_cash_move.payment_method_id = PaymentMethod.find_by(:isCash => true).id
  187. new_cash_move.quantity = moves.sum(:quantity)
  188. new_cash_move.move_type = :egreso
  189. new_cash_move.sale_id = moves[0].sale_id
  190. new_cash_move.concept = :sale
  191. new_cash_move.ticket = moves[0].sale.sale_code
  192. new_cash_move.status = :active
  193. new_cash_move.save
  194. else
  195. moves.destroy_all
  196. end
  197. end
  198. elsif @sale.credit?
  199. credit = Credit.find_by(:sale_id => @sale.id, :customer_id => @sale.customer_id)
  200. credit.update_attributes(:status => :cancelled)
  201. end
  202. @sale.sales_details.each do |detail|
  203. detail.update_attributes(:status => :inactive)
  204. stockProduct = AvailableProduct.find_by(:product_id => detail.product_id, :pointsale_id => @sale.get_pointsale.id)
  205. unless stockProduct.blank?
  206. # sumarle al stock del producto
  207. stock = stockProduct.stock + detail.quantity
  208. stockProduct.update_attributes(:stock => stock)
  209. # guardar en bitacora de inventario
  210. move = InventoriesMove.new
  211. move.product_id = detail.product_id
  212. move.sale_id = @sale.id
  213. move.quantity = detail.quantity
  214. move.move_type = "incoming"
  215. move.reason = @sale.reserved? ? "sale_reserved_cancelled" : "sale_cancel"
  216. move.save
  217. end
  218. end
  219. format.html { redirect_to (@sale.reserved? ? sales_reserved_path : sales_url),
  220. warning: (@sale.reserved? ? "Apartado con folio #{@sale.sale_code} cancelado." : "Venta con folio #{@sale.sale_code} cancelado.") }
  221. format.json { head :no_content }
  222. end
  223. end
  224. end
  225. def find_sales_by_date
  226. respond_to do |format|
  227. startDate = DateTime.parse(params[:begin_date])
  228. endDate = DateTime.parse(params[:end_date])
  229. if current_user.usertype == 'A'
  230. @sales = Sale.where(:date_sale => startDate..endDate).where('saletype != 2').order(" created_at DESC ")
  231. else
  232. @sales = Pointsale.find(current_user.pointsale_id).sales.where(:date_sale => startDate..endDate).where('saletype != 2').order(" created_at DESC ")
  233. end
  234. format.js
  235. end
  236. end
  237. def find_customer_sales_by_date
  238. respond_to do |format|
  239. startDate = DateTime.parse(params[:begin_date])
  240. endDate = DateTime.parse(params[:end_date])
  241. cliente = params[:cliente]
  242. @sales = Sale.where(:date_sale => startDate..endDate, :customer_id => cliente).where('saletype != 2').order(" id DESC ")
  243. format.js { render :action => "find_sales_by_date" }
  244. end
  245. end
  246. def find_reserved_sales_by_date
  247. respond_to do |format|
  248. startDate = DateTime.parse(params[:begin_date])
  249. endDate = DateTime.parse(params[:end_date])
  250. if current_user.usertype == 'A'
  251. @sales = Sale.where(:date_sale => startDate..endDate, :saletype => 2).order(" created_at DESC ")
  252. else
  253. @sales = Pointsale.find(current_user.pointsale_id).sales.where(:date_sale => startDate..endDate).where('saletype = 2').order(" created_at DESC ")
  254. end
  255. format.js
  256. end
  257. end
  258. def return_expired
  259. @sale = Sale.find(params[:sale_id])
  260. respond_to do |format|
  261. if @sale.update_attributes(:status => :cancelled_by_expiration)
  262. @sale.sales_details.each do |detail|
  263. detail.update_attributes(:status => :inactive)
  264. stockProduct = AvailableProduct.find_by(:product_id => detail.product_id, :pointsale_id => @sale.get_pointsale.id)
  265. unless stockProduct.blank?
  266. # sumarle al stock del producto
  267. stock = stockProduct.stock + detail.quantity
  268. stockProduct.update_attributes(:stock => stock)
  269. # guardar en bitacora de inventario
  270. move = InventoriesMove.new
  271. move.product_id = detail.product_id
  272. move.sale_id = @sale.id
  273. move.quantity = detail.quantity
  274. move.move_type = "incoming"
  275. move.reason = "sale_expired"
  276. move.save
  277. end
  278. end
  279. format.html { redirect_to sales_reserved_url, warning: "Productos reingresados al inventario del apartado #{@sale.sale_code}." }
  280. format.json { head :no_content }
  281. end
  282. end
  283. end
  284. def liquidate_reserve
  285. respond_to do |format|
  286. @sale = Sale.find(params[:sale_id])
  287. @payments = CashRegistersMove.where(:sale_id => @sale.id, :status => 1)
  288. format.js { redirect_to new_cash_registers_move_path(:sale => @sale.id) }
  289. end
  290. end
  291. def cancel_reserved_sale
  292. @sale = Sale.find(params[:sale_id])
  293. end
  294. def print_receipt
  295. #ticket para la venta
  296. respond_to do |format|
  297. sale = Sale.find(params[:sale_id])
  298. format.pdf do
  299. render pdf: "ticket_venta_#{sale.id}",
  300. template: "sales/receipt.pdf.erb",
  301. layout: 'receipt.html.erb',
  302. locals: { :sale => sale },
  303. show_as_html: params.key?('debug'),
  304. page_width: '80mm',
  305. page_height: '300mm'
  306. end
  307. end
  308. end
  309. def print_reserve_receipt
  310. #ticket para apartado
  311. respond_to do |format|
  312. sale = Sale.find(params[:sale_id])
  313. # debt = sale.cash_registers_moves.first.quantity
  314. debt = sale.cash_registers_moves.sum(:quantity)
  315. format.pdf do
  316. render pdf: "ticket_apartado_#{sale.id}",
  317. template: "sales/receipt_reserve.pdf.erb",
  318. layout: 'receipt.html.erb',
  319. locals: { :sale => sale, :debt => debt },
  320. show_as_html: params.key?('debug'),
  321. page_width: '80mm',
  322. page_height: '300mm'
  323. end
  324. end
  325. end
  326. def print_credit_receipt
  327. #ticket para credito
  328. respond_to do |format|
  329. sale = Sale.find(params[:sale_id])
  330. debt = 0
  331. sale.customer.credits.activos.each do |credit|
  332. debt += credit.rest
  333. end
  334. format.pdf do
  335. render pdf: "ticket_credito_#{sale.id}",
  336. template: "sales/receipt_credit.pdf.erb",
  337. layout: 'receipt.html.erb',
  338. locals: { :sale => sale, :debt => debt },
  339. show_as_html: params.key?('debug'),
  340. page_width: '80mm',
  341. page_height: '300mm'
  342. end
  343. end
  344. end
  345. def print_partial_payment_receipt
  346. #ticket para abonos a apartado
  347. respond_to do |format|
  348. sale = Sale.find(params[:sale_id])
  349. new_moves = CashRegistersMove.where(id: params[:new_moves_array])
  350. quantity = new_moves.sum(:quantity)
  351. format.pdf do
  352. render pdf: "ticket_abono_apartado_#{sale.id}",
  353. template: "sales/receipt_partial_payment.pdf.erb",
  354. layout: 'receipt.html.erb',
  355. locals: { :sale => sale, :new_payments_quantity => quantity, :moves => new_moves },
  356. show_as_html: params.key?('debug'),
  357. page_width: '80mm',
  358. page_height: '300mm'
  359. end
  360. end
  361. end
  362. def print_credit_payment_receipt
  363. #ticket para abonos a credito
  364. respond_to do |format|
  365. sale = Sale.find(params[:sale_id])
  366. deuda = params[:debts]
  367. cash_move = CashRegistersMove.where(:sale_id => sale.id).last
  368. quantity = cash_move.quantity
  369. debt = Credit.where(:customer_id => sale.customer_id).sum(:rest)
  370. format.pdf do
  371. render pdf: "ticket_abono_credito_#{sale.id}",
  372. template: "sales/receipt_credit_payment.pdf.erb",
  373. layout: 'receipt.html.erb',
  374. locals: { :sale => sale, :new_payment => quantity, :debt => debt, :deuda => deuda, :move => cash_move },
  375. show_as_html: params.key?('debug'),
  376. page_width: '80mm',
  377. page_height: '300mm'
  378. end
  379. end
  380. end
  381. def add_haggle
  382. @pre_sale = PreSale.find(params[:pre_sale])
  383. @suggested_haggle = (@pos_config.haggle_in_sale_percent.to_f / 100) * @pre_sale.unit_price
  384. end
  385. def create_haggle
  386. respond_to do |format|
  387. @pre_sale = PreSale.find(params[:pre_sale])
  388. @pre_sale.haggle = params[:haggle].to_f
  389. @pre_sale.get_totals
  390. if @pre_sale.save
  391. format.js
  392. end
  393. end
  394. end
  395. def find_sales_by_dates_or_code
  396. respond_to do |format|
  397. if params[:sale_code].present?
  398. @sales = Pointsale.find(current_user.pointsale_id).sales.activas.where(:sale_code => params[:sale_code], :saletype => 1).order("id DESC")
  399. else
  400. start_date = DateTime.parse(params[:start_date])
  401. end_date = DateTime.parse(params[:end_date])
  402. product_id = params[:product_id]
  403. if product_id.present?
  404. @sales = Pointsale.find(current_user.pointsale_id).sales.activas.where(:date_sale => start_date..end_date, :saletype => 1).joins(:sales_details).where('sales_details.product_id = (?)', product_id).order("id DESC")
  405. else
  406. @sales = Pointsale.find(current_user.pointsale_id).sales.activas.where(:date_sale => start_date..end_date, :saletype => 1).joins(:sales_details).order("id DESC")
  407. end
  408. end
  409. format.js
  410. end
  411. end
  412. private
  413. # Use callbacks to share common setup or constraints between actions.
  414. def set_sale
  415. @sale = Sale.find(params[:id])
  416. end
  417. def get_filters
  418. if params[:current_page].blank?
  419. @current_page = 1
  420. else
  421. @current_page = params[:current_page]
  422. end
  423. @filter = params[:filter]
  424. end
  425. # Never trust parameters from the scary internet, only allow the white list through.
  426. def sale_params
  427. params.require(:sale).permit(:customer_id, :saletype, :amount, :tax, :discount, :total, :date_sale, :user_id, :seller_id, :sale_code, :credit_note)
  428. end
  429. end