diff --git a/app/controllers/api/cart_controller.rb b/app/controllers/api/cart_controller.rb index 14f3becb5..c9de2170d 100644 --- a/app/controllers/api/cart_controller.rb +++ b/app/controllers/api/cart_controller.rb @@ -9,7 +9,7 @@ class API::CartController < API::ApiController def create authorize :cart, :create? - @order ||= Cart::FindOrCreateService.new.call(order_token, current_user) + @order ||= Cart::FindOrCreateService.new(current_user).call(order_token) render 'api/orders/show' end diff --git a/app/models/order.rb b/app/models/order.rb index 898195af6..4bcee9766 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -17,6 +17,7 @@ class Order < PaymentDocument validates :token, :state, presence: true before_create :add_environment + after_create :update_reference delegate :user, to: :statistic_profile diff --git a/app/models/payment_document.rb b/app/models/payment_document.rb index 1f2ef946c..40aa03420 100644 --- a/app/models/payment_document.rb +++ b/app/models/payment_document.rb @@ -4,8 +4,8 @@ class PaymentDocument < Footprintable self.abstract_class = true - def generate_reference(date = DateTime.current) - self.reference = PaymentDocumentService.generate_reference(self, date: date) + def generate_reference + self.reference = PaymentDocumentService.generate_order_number(self) end def update_reference diff --git a/app/policies/cart_policy.rb b/app/policies/cart_policy.rb index 0aad87849..4bacdda1e 100644 --- a/app/policies/cart_policy.rb +++ b/app/policies/cart_policy.rb @@ -10,7 +10,7 @@ class CartPolicy < ApplicationPolicy define_method "#{action}?" do return user.privileged? || (record.statistic_profile_id == user.statistic_profile.id) if user - record.statistic_profile_id.nil? + record.statistic_profile_id.nil? && record.operator_profile_id.nil? end end end diff --git a/app/services/cart/find_or_create_service.rb b/app/services/cart/find_or_create_service.rb index cb48dc159..ec506c0e2 100644 --- a/app/services/cart/find_or_create_service.rb +++ b/app/services/cart/find_or_create_service.rb @@ -2,46 +2,23 @@ # Provides methods for find or create a cart class Cart::FindOrCreateService - def call(order_token, user) - order = Order.find_by(token: order_token, state: 'cart') + def initialize(user) + @user = user + end - if order && user && ((user.member? && order.statistic_profile_id.present? && order.statistic_profile_id != user.statistic_profile.id) || - (user.privileged? && order.operator_profile_id.present? && order.operator_profile_id != user.invoicing_profile.id)) - order = nil - end - order = nil if order && !user && order.statistic_profile_id.present? - if order && order.statistic_profile_id.present? && Order.where(statistic_profile_id: order.statistic_profile_id, - payment_state: 'paid').where('created_at > ?', order.created_at).last.present? - order = nil - end + def call(order_token) + @order = Order.find_by(token: order_token, state: 'cart') + check_order_authorization + set_last_cart_if_user_login if @order.nil? - if order.nil? - if user&.member? - last_paid_order = Order.where(statistic_profile_id: user.statistic_profile.id, - payment_state: 'paid').last - order = if last_paid_order - Order.where(statistic_profile_id: user.statistic_profile.id, - state: 'cart').where('created_at > ?', last_paid_order.created_at).last - else - Order.where(statistic_profile_id: user.statistic_profile.id, state: 'cart').last - end + if @order + if @order.order_items.count.zero? && @user && ((@user.member? && @order.statistic_profile_id.nil?) || (@user.privileged? && @order.operator_profile_id.nil?)) + set_last_order_if_anonymous_order_s_items_is_empty_after_user_login end - if user&.privileged? - last_paid_order = Order.where(operator_profile_id: user.invoicing_profile.id, - payment_state: 'paid').last - order = if last_paid_order - Order.where(operator_profile_id: user.invoicing_profile.id, - state: 'cart').where('created_at > ?', last_paid_order.created_at).last - else - Order.where(operator_profile_id: user.invoicing_profile.id, state: 'cart').last - end - end - end - - if order - order.update(statistic_profile_id: user.statistic_profile.id) if order.statistic_profile_id.nil? && user&.member? - order.update(operator_profile_id: user.invoicing_profile.id) if order.operator_profile_id.nil? && user&.privileged? - return order + clean_old_cart if @user + @order.update(statistic_profile_id: @user.statistic_profile.id) if @order.statistic_profile_id.nil? && @user&.member? + @order.update(operator_profile_id: @user.invoicing_profile.id) if @order.operator_profile_id.nil? && @user&.privileged? + return @order end token = GenerateTokenService.new.call(Order) @@ -50,11 +27,114 @@ class Cart::FindOrCreateService state: 'cart', total: 0 } - if user - order_param[:statistic_profile_id] = user.statistic_profile.id if user.member? + if @user + order_param[:statistic_profile_id] = @user.statistic_profile.id if @user.member? - order_param[:operator_profile_id] = user.invoicing_profile.id if user.privileged? + order_param[:operator_profile_id] = @user.invoicing_profile.id if @user.privileged? end Order.create!(order_param) end + + # This function check current order that + # 1. belongs current user + # 2. has belonged an user but this user dont login + # 3. created date > last paid order of user + # if not, set current order = nil + def check_order_authorization + if @order && @user && ((@user.member? && @order.statistic_profile_id.present? && @order.statistic_profile_id != @user.statistic_profile.id) || + (@user.privileged? && @order.operator_profile_id.present? && @order.operator_profile_id != @user.invoicing_profile.id)) + @order = nil + end + @order = nil if @order && !@user && (@order.statistic_profile_id.present? || @order.operator_profile_id.present?) + if @order && @order.statistic_profile_id.present? && Order.where(statistic_profile_id: @order.statistic_profile_id, + payment_state: 'paid').where('created_at > ?', @order.created_at).last.present? + @order = nil + end + if @order && @order.operator_profile_id.present? && Order.where(operator_profile_id: @order.operator_profile_id, + payment_state: 'paid').where('created_at > ?', @order.created_at).last.present? + @order = nil + end + end + + # set user last cart of user when login + def set_last_cart_if_user_login + if @user&.member? + last_paid_order = Order.where(statistic_profile_id: @user.statistic_profile.id, + payment_state: 'paid').last + @order = if last_paid_order + Order.where(statistic_profile_id: @user.statistic_profile.id, + state: 'cart').where('created_at > ?', last_paid_order.created_at).last + else + Order.where(statistic_profile_id: @user.statistic_profile.id, state: 'cart').last + end + end + if @user&.privileged? + last_paid_order = Order.where(operator_profile_id: @user.invoicing_profile.id, + payment_state: 'paid').last + @order = if last_paid_order + Order.where(operator_profile_id: @user.invoicing_profile.id, + state: 'cart').where('created_at > ?', last_paid_order.created_at).last + else + Order.where(operator_profile_id: @user.invoicing_profile.id, state: 'cart').last + end + end + end + + # set last order if current cart is anoymous and user is login + def set_last_order_if_anonymous_order_s_items_is_empty_after_user_login + last_unpaid_order = nil + if @user&.member? + last_paid_order = Order.where(statistic_profile_id: @user.statistic_profile.id, + payment_state: 'paid').last + last_unpaid_order = if last_paid_order + Order.where(statistic_profile_id: @user.statistic_profile.id, + state: 'cart').where('created_at > ?', last_paid_order.created_at).last + else + Order.where(statistic_profile_id: @user.statistic_profile.id, state: 'cart').last + end + end + if @user&.privileged? + last_paid_order = Order.where(operator_profile_id: @user.invoicing_profile.id, + payment_state: 'paid').last + last_unpaid_order = if last_paid_order + Order.where(operator_profile_id: @user.invoicing_profile.id, + state: 'cart').where('created_at > ?', last_paid_order.created_at).last + else + Order.where(operator_profile_id: @user.invoicing_profile.id, state: 'cart').last + end + end + if last_unpaid_order && last_unpaid_order.id != @order.id + @order.destroy + @order = last_unpaid_order + end + end + + # delete all old cart if last cart of user isnt empty + # keep every user only one cart + def clean_old_cart + if @user&.member? + Order.where(statistic_profile_id: @user.statistic_profile.id, state: 'cart') + .where.not(id: @order.id) + .destroy_all + end + if @user&.privileged? + Order.where(operator_profile_id: @user.invoicing_profile.id, state: 'cart') + .where.not(id: @order.id) + .destroy_all + end + end + + # delete all empty cart if last cart of user isnt empty + def clean_empty_cart + if @user&.member? + Order.where(statistic_profile_id: @user.statistic_profile.id, state: 'cart') + .where('(SELECT COUNT(*) FROM order_items WHERE order_items.order_id = orders.id) = 0') + .destroy_all + end + if @user&.privileged? + Order.where(operator_profile_id: @user.invoicing_profile.id, state: 'cart') + .where('(SELECT COUNT(*) FROM order_items WHERE order_items.order_id = orders.id) = 0') + .destroy_all + end + end end diff --git a/app/services/payment_document_service.rb b/app/services/payment_document_service.rb index 99ecda9ea..4d099ed84 100644 --- a/app/services/payment_document_service.rb +++ b/app/services/payment_document_service.rb @@ -32,18 +32,6 @@ class PaymentDocumentService reference.gsub!(/X\[([^\]]+)\]/, ''.to_s) end - # remove information about refunds (R[text]) - reference.gsub!(/R\[([^\]]+)\]/, ''.to_s) - # remove information about payment schedule (S[text]) - reference.gsub!(/S\[([^\]]+)\]/, ''.to_s) - elsif document.is_a? Order - # information about online selling (X[text]) - if document.paid_by_card? - reference.gsub!(/X\[([^\]]+)\]/, '\1') - else - reference.gsub!(/X\[([^\]]+)\]/, ''.to_s) - end - # remove information about refunds (R[text]) reference.gsub!(/R\[([^\]]+)\]/, ''.to_s) # remove information about payment schedule (S[text]) @@ -55,16 +43,16 @@ class PaymentDocumentService reference end - def generate_order_number(invoice) + def generate_order_number(document) pattern = Setting.get('invoice_order-nb') # global document number (nn..nn) reference = pattern.gsub(/n+(?![^\[]*\])/) do |match| - pad_and_truncate(number_of_invoices('global'), match.to_s.length) + pad_and_truncate(number_of_invoices(document.is_a?(Order) ? 'order' : 'global'), match.to_s.length) end - reference = replace_invoice_number_pattern(reference, invoice.created_at) - replace_date_pattern(reference, invoice.created_at) + reference = replace_invoice_number_pattern(reference, document.created_at) + replace_date_pattern(reference, document.created_at) end private @@ -95,13 +83,14 @@ class PaymentDocumentService when 'year' start = date.beginning_of_year else - return get_max_id(Invoice) + get_max_id(PaymentSchedule) + return get_max_id(Invoice) + get_max_id(PaymentSchedule) + get_max_id(Order) end ending = date - return Invoice.count + PaymentSchedule.count unless defined? start + return Invoice.count + PaymentSchedule.count + Order.count unless defined? start Invoice.where('created_at >= :start_date AND created_at <= :end_date', start_date: start, end_date: ending).length + - PaymentSchedule.where('created_at >= :start_date AND created_at <= :end_date', start_date: start, end_date: ending).length + PaymentSchedule.where('created_at >= :start_date AND created_at <= :end_date', start_date: start, end_date: ending).length + + Order.where('created_at >= :start_date AND created_at <= :end_date', start_date: start, end_date: ending).length end ## @@ -113,21 +102,21 @@ class PaymentDocumentService copy = reference.dup # full year (YYYY) - copy.gsub!(/YYYY(?![^\[]*\])/, date.strftime('%Y')) + copy.gsub!(/(?![^\[]*\])YYYY(?![^\[]*\])/, date.strftime('%Y')) # year without century (YY) - copy.gsub!(/YY(?![^\[]*\])/, date.strftime('%y')) + copy.gsub!(/(?![^\[]*\])YY(?![^\[]*\])/, date.strftime('%y')) # abbreviated month name (MMM) - copy.gsub!(/MMM(?![^\[]*\])/, date.strftime('%^b')) + copy.gsub!(/(?![^\[]*\])MMM(?![^\[]*\])/, date.strftime('%^b')) # month of the year, zero-padded (MM) - copy.gsub!(/MM(?![^\[]*\])/, date.strftime('%m')) + copy.gsub!(/(?![^\[]*\])MM(?![^\[]*\])/, date.strftime('%m')) # month of the year, non zero-padded (M) - copy.gsub!(/M(?![^\[]*\])/, date.strftime('%-m')) + copy.gsub!(/(?![^\[]*\])M(?![^\[]*\])/, date.strftime('%-m')) # day of the month, zero-padded (DD) - copy.gsub!(/DD(?![^\[]*\])/, date.strftime('%d')) + copy.gsub!(/(?![^\[]*\])DD(?![^\[]*\])/, date.strftime('%d')) # day of the month, non zero-padded (DD) - copy.gsub!(/DD(?![^\[]*\])/, date.strftime('%-d')) + copy.gsub!(/(?![^\[]*\])DD(?![^\[]*\])/, date.strftime('%-d')) copy end diff --git a/app/services/payments/payment_concern.rb b/app/services/payments/payment_concern.rb index 9148cf7ae..5e2686ff9 100644 --- a/app/services/payments/payment_concern.rb +++ b/app/services/payments/payment_concern.rb @@ -35,7 +35,6 @@ module Payments::PaymentConcern order.order_items.each do |item| ProductService.update_stock(item.orderable, 'external', 'sold', -item.quantity, item.id) end - order.reference = order.generate_reference order.save order.reload end