完成用户log

This commit is contained in:
qyzh 2020-10-20 19:58:08 +08:00
parent faf2302b8e
commit 1ac5498091
36 changed files with 463 additions and 25 deletions

View File

@ -103,6 +103,7 @@ gem 'rails-i18n', '~> 5.1'
# job
gem 'sidekiq'
gem 'sinatra'
gem 'whenever'
# batch insert
gem 'bulk_insert'
@ -128,3 +129,7 @@ gem 'request_store'
gem 'harmonious_dictionary', '~> 0.0.1'
gem 'parallel', '~> 1.19', '>= 1.19.1'
# log
gem 'multi_logger'

View File

@ -102,6 +102,7 @@ GEM
chromedriver-helper (2.1.1)
archive-zip (~> 0.10)
nokogiri (~> 1.8)
chronic (0.10.2)
chunky_png (1.3.11)
concurrent-ruby (1.1.6)
connection_pool (2.2.2)
@ -186,6 +187,8 @@ GEM
minitest (5.14.0)
msgpack (1.3.3)
multi_json (1.14.1)
multi_logger (0.2.0)
railties
multi_xml (0.6.0)
multipart-post (2.1.1)
mustermann (1.1.1)
@ -423,6 +426,8 @@ GEM
websocket-driver (0.7.1)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.4)
whenever (1.0.0)
chronic (>= 0.6.3)
wkhtmltopdf-binary (0.12.5.4)
xpath (3.2.0)
nokogiri (~> 1.8)
@ -460,6 +465,7 @@ DEPENDENCIES
jquery-rails
kaminari (~> 1.1, >= 1.1.1)
listen (>= 3.0.5, < 3.2)
multi_logger
mysql2 (>= 0.4.4, < 0.6.0)
oauth2
omniauth (~> 1.9.0)
@ -500,6 +506,7 @@ DEPENDENCIES
tzinfo-data
uglifier (>= 1.3.0)
web-console (>= 3.3.0)
whenever
wkhtmltopdf-binary
RUBY VERSION

View File

@ -0,0 +1,2 @@
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.

View File

@ -0,0 +1,2 @@
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.

View File

@ -0,0 +1,3 @@
// Place all the styles related to the log controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View File

@ -0,0 +1,3 @@
// Place all the styles related to the Wallets controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

View File

@ -15,6 +15,7 @@ class ApplicationController < ActionController::Base
before_action :check_sign
before_action :user_setup
#before_action :check_account
after_action :user_trace_log
# TODO
# check sql query time
@ -342,7 +343,7 @@ class ApplicationController < ActionController::Base
elsif params[:debug] == 'student'
User.current = User.find 8686
elsif params[:debug] == 'admin'
user = User.find 1
user = User.find 4
User.current = user
cookies.signed[:user_id] = user.id
end
@ -367,6 +368,12 @@ class ApplicationController < ActionController::Base
end
end
def user_trace_log
user = current_user
# print("*********************url:", request.url, "****routes", request.request_method)
Rails.logger.user_trace.info("{id: #{user.id}, login: #{user.login}, url: #{request.url}, params: #{params}, response_code: #{response.code}, time: #{Time.now}}")
end
def try_to_autologin
if cookies[autologin_cookie_name]
# auto-login feature starts a new session
@ -384,7 +391,7 @@ class ApplicationController < ActionController::Base
def current_user
if Rails.env.development?
User.current = User.find 1
User.current = User.find 4
else
User.current
end

View File

@ -0,0 +1,19 @@
class LogController < ApplicationController
def file_list
path = "#{Rails.root}/log"
@file_list = []
Dir.foreach(path) do |file|
@file_list << file
end
@file_list = @file_list.sort
end
def download
path = "#{Rails.root}/log/#{params[:filename]}"
if params[:filename] && File.exist?(path) && File.file?(path)
send_file(path, filename: params[:filename])
else
render json: { message: 'no such file!' }
end
end
end

View File

@ -7,6 +7,50 @@ class SponsorshipsController < ApplicationController
@sponsorships = Sponsorship.all
end
def stopped
@stopped_sponsorships = StoppedSponsorship.all
end
def sponsored
if User.current.id == Integer(params[:id])
@sponsorships = Sponsorship.where("developer_id=?", params[:id])
else
@sponsorships = Sponsorship.where("developer_id=? AND visible=1", params[:id])
end
@total = @sponsorships.length
@sponsorships = kaminari_paginate(@sponsorships)
end
def sponsoring
if User.current.id == Integer(params[:id])
@sponsorships = Sponsorship.where("sponsor_id=?", params[:id])
else
@sponsorships = Sponsorship.where("sponsor_id=? AND visible=1", params[:id])
end
@total = @sponsorships.length
@sponsorships = kaminari_paginate(@sponsorships)
end
def stopped_sponsored
if User.current.id == Integer(params[:id])
@stopped_sponsorships = StoppedSponsorship.where("developer_id=?", params[:id])
else
@stopped_sponsorships = StoppedSponsorship.where("developer_id=? AND visible=1", params[:id])
end
@total = @stopped_sponsorships.length
@stopped_sponsorships = kaminari_paginate(@stopped_sponsorships)
end
def stopped_sponsoring
if User.current.id == Integer(params[:id])
@stopped_sponsorships = StoppedSponsorship.where("sponsor_id=?", params[:id])
else
@stopped_sponsorships = StoppedSponsorship.where("sponsor_id=? AND visible=1", params[:id])
end
@total = @stopped_sponsorships.length
@stopped_sponsorships = kaminari_paginate(@stopped_sponsorships)
end
# GET /sponsorships/1
# GET /sponsorships/1.json
def show
@ -24,40 +68,65 @@ class SponsorshipsController < ApplicationController
# POST /sponsorships
# POST /sponsorships.json
def create
@sponsorship = Sponsorship.new(sponsorship_params)
sponsor_id = User.current.id
check_sponsorship = Sponsorship.where("sponsor_id=? AND developer_id=?", sponsor_id, params[:developer_id])
respond_to do |format|
if @sponsorship.save
format.html { redirect_to @sponsorship, notice: 'Sponsorship was successfully created.' }
format.json { render :show, status: :created, location: @sponsorship }
@sponsorship = Sponsorship.new(sponsorship_params.merge({sponsor_id: sponsor_id}))
# print('#######################', params[:single].class)
unless check_sponsorship.length.zero? || params[:single]
return render json: {status: -1, message: '您已赞助了TA' }
end
if @sponsorship.pay && @sponsorship.save
if params[:single] && @sponsorship.stop
return render json: { status: 1, message: '赞助成功' }
elsif !params[:single]
User.current.update(sponsor_num: User.current.sponsor_num+1)
@sponsorship.developer.update(sponsored_num: @sponsorship.developer.sponsored_num + 1)
return render json: { status: 1, message: '赞助成功' }
else
format.html { render :new }
format.json { render json: @sponsorship.errors, status: :unprocessable_entity }
return render json: { status: -1, message: '赞助失败' }
end
end
# return render_result message: '赞助成功' if @sponsorship.save
# respond_to do |format|
# if check_sponsorship.length.zero? && @sponsorship.save
# format.html { redirect_to @sponsorship, notice: 'Sponsorship was successfully created.' }
# format.json { render :show, status: :created, location: @sponsorship }
# # render_result status=0, message="赞助成功"
# else
# format.html { render :new }
# format.json { render json: @sponsorship.errors, status: :unprocessable_entity }
# end
# end
end
# PATCH/PUT /sponsorships/1
# PATCH/PUT /sponsorships/1.json
def update
respond_to do |format|
if @sponsorship.update(sponsorship_params)
format.html { redirect_to @sponsorship, notice: 'Sponsorship was successfully updated.' }
format.json { render :show, status: :ok, location: @sponsorship }
else
format.html { render :edit }
format.json { render json: @sponsorship.errors, status: :unprocessable_entity }
end
end
# respond_to do |format|
# if @sponsorship.update(sponsorship_params)
# format.html { redirect_to @sponsorship, notice: 'Sponsorship was successfully updated.' }
# format.json { render :show, status: :ok, location: @sponsorship }
# else
# format.html { render :edit }
# format.json { render json: @sponsorship.errors, status: :unprocessable_entity }
# end
# end
end
# DELETE /sponsorships/1
# DELETE /sponsorships/1.json
def destroy
@sponsorship.destroy
respond_to do |format|
format.html { redirect_to sponsorships_url, notice: 'Sponsorship was successfully destroyed.' }
format.json { head :no_content }
# @sponsorship.destroy
# respond_to do |format|
# format.html { redirect_to sponsorships_url, notice: 'Sponsorship was successfully destroyed.' }
# format.json { head :no_content }
# end
if (User.current.id == @sponsorship.developer.id || User.current.id == @sponsorship.sponsor.id) && @sponsorship.stop
render json: {status: 1, message: "终止成功"}
else
render json: {status: -1, message: "失败"}
end
end
@ -69,6 +138,6 @@ class SponsorshipsController < ApplicationController
# Only allow a list of trusted parameters through.
def sponsorship_params
params.require(:sponsorship).permit(:amount, :visible, :sponsor_id, :developer_id)
params.require(:sponsorship).permit(:amount, :visible, :sponsor_id, :developer_id, :single, :page, :limit, :sort_by, :search)
end
end

View File

@ -0,0 +1,28 @@
class WalletsController < ApplicationController
def balance
user = User.find_by_id(params[:id])
user.create_wallet(balance: 0) if user.wallet.nil?
@wallet = user.wallet
end
def coin_changes
user = User.find_by_id(params[:id])
user.create_wallet(balance: 0) if user.wallet.nil?
@wallet = user.wallet
if params[:category] == 'all'
scope = CoinChange.where('to_wallet_id = ? OR from_wallet_id = ?', @wallet.id, @wallet.id)
elsif params[:category] == 'income'
# @coin_changes = CoinChange.where('to_wallet_id = ?', @wallet.id).limit(100)
scope = @wallet.income
elsif params[:category] == 'outcome'
scope = @wallet.outcome
end
sort = params[:sort_by] || "created_at"
sort_direction = params[:sort_direction] || "desc"
scope = scope.reorder("#{sort} #{sort_direction}")
@total = scope.length
@coin_changes = kaminari_paginate(scope)
end
end

View File

@ -0,0 +1,2 @@
module LogHelper
end

View File

@ -0,0 +1,2 @@
module WalletsHelper
end

View File

@ -0,0 +1,15 @@
class MonthlyPaymentWorker
include Sidekiq::Worker
include Sidetiq::Schedulable
recurrence do
minutely(2)
# monthly.day_of_month(12) #每月的12号0点执行
# monthly.day_of_month(23).hour_of_day(20) #每月的12号1点执行
end
def perform(*args)
Sponsorship.monthly_payment
puts Time.now, 'sponsor payment done'
end
end

View File

@ -2,4 +2,35 @@ class Sponsorship < ApplicationRecord
belongs_to :sponsor, class_name: 'User'
belongs_to :developer, class_name: 'User'
validates :amount, presence: true
def stop
stopped_sponsorship = StoppedSponsorship.new(developer_id: developer_id, sponsor_id: sponsor_id, start_time: created_at, amount: amount, visible: visible, accumulate: accumulate)
stopped_sponsorship.save && destroy
end
def pay
sponsor.create_wallet(balance: 0) if sponsor.wallet.nil?
developer.create_wallet(balance: 0) if developer.wallet.nil?
sponsor_wallet = sponsor.wallet
developer_wallet = developer.wallet
return false if sponsor.wallet.balance < amount
reason = "#{sponsor.full_name}#{developer.full_name}的赞助支付。"
coinchange = CoinChange.new(amount: amount, reason: reason, to_wallet_id: developer_wallet.id, from_wallet_id: sponsor_wallet.id)
if coinchange.save
sponsor_wallet.update(balance: sponsor_wallet.balance -= amount)
developer_wallet.update(balance: developer_wallet.balance += amount)
update(accumulate: self.accumulate += amount)
return true
end
false
end
def self.monthly_payment
sponsorships = Sponsorship.all
sponsorships.each do |s|
s.stop unless s.pay
end
end
end

View File

@ -0,0 +1 @@
json.array! @file_list

View File

@ -1,2 +1,2 @@
json.extract! sponsorship, :id, :amount, :visible, :sponsor_id, :developer_id, :created_at, :updated_at
json.extract! sponsorship, :id, :amount, :visible, :sponsor_id, :developer_id, :created_at, :updated_at, :accumulate
json.url sponsorship_url(sponsorship, format: :json)

View File

@ -0,0 +1,20 @@
json.count @total
json.sponsorships do
json.array! @sponsorships do |sponsorship|
json.id sponsorship.id
json.start_time sponsorship.created_at.to_date
# json.stop_time '-'
if sponsorship.visible.zero?
json.visible false
else
json.visible true
end
json.amount sponsorship.amount
sponsor = sponsorship.sponsor
json.image_url url_to_avatar(sponsor)
json.username sponsor.full_name
json.user_id sponsor.id
json.login sponsor.login
json.accumulate sponsorship.accumulate
end
end

View File

@ -0,0 +1,20 @@
json.count @total
json.sponsorships do
json.array! @sponsorships do |sponsorship|
json.id sponsorship.id
json.start_time sponsorship.created_at.to_date
# json.stop_time '-'
if sponsorship.visible.zero?
json.visible false
else
json.visible true
end
json.amount sponsorship.amount
sponsor = sponsorship.developer
json.image_url url_to_avatar(sponsor)
json.username sponsor.full_name
json.user_id sponsor.id
json.login sponsor.login
json.accumulate sponsorship.accumulate
end
end

View File

@ -0,0 +1,11 @@
json.array! @stopped_sponsorships do |sponsorship|
json.id sponsorship.id
json.amount sponsorship.amount
json.visible sponsorship.visible
json.sponsor_id sponsorship.sponsor_id
json.developer_id sponsorship.developer_id
json.start_time sponsorship.start_time
json.created_at sponsorship.created_at
json.updated_at sponsorship.updated_at
json.accumulate sponsorship.accumulate
end

View File

@ -0,0 +1,20 @@
json.count @total
json.sponsorships do
json.array! @stopped_sponsorships do |sponsorship|
json.id sponsorship.id
json.start_time sponsorship.start_time.to_date
json.stop_time sponsorship.created_at.to_date
if sponsorship.visible.zero?
json.visible false
else
json.visible true
end
json.amount sponsorship.amount
sponsor = sponsorship.sponsor
json.image_url url_to_avatar(sponsor)
json.username sponsor.full_name
json.user_id sponsor.id
json.login sponsor.login
json.accumulate sponsorship.accumulate
end
end

View File

@ -0,0 +1,20 @@
json.count @total
json.sponsorships do
json.array! @stopped_sponsorships do |sponsorship|
json.id sponsorship.id
json.start_time sponsorship.start_time.to_date
json.stop_time sponsorship.created_at.to_date
if sponsorship.visible.zero?
json.visible false
else
json.visible true
end
json.amount sponsorship.amount
sponsor = sponsorship.developer
json.image_url url_to_avatar(sponsor)
json.username sponsor.full_name
json.user_id sponsor.id
json.login sponsor.login
json.accumulate sponsorship.accumulate
end
end

View File

@ -0,0 +1,2 @@
<h1>Wallets#balance</h1>
<p>Find me in app/views/wallets/balance.html.erb</p>

View File

@ -0,0 +1 @@
json.balance @wallet.balance

View File

@ -0,0 +1,16 @@
json.balance @wallet.balance
json.count @total
json.coin_changes do
json.array! @coin_changes do |coin_change|
from_user = coin_change.from_wallet.user
to_user = coin_change.to_wallet.user
json.amount coin_change.amount
json.from_user from_user.full_name
json.from_user_login from_user.login
json.to_user to_user.full_name
json.to_user_login to_user.login
json.description coin_change.description
json.reason coin_change.reason
json.date coin_change.created_at.to_date
end
end

View File

@ -55,6 +55,9 @@ Rails.application.configure do
# Suppress logger output for asset requests.
config.assets.quiet = true
# config.logger = Logger.new("#{Rails.root}/log/#{Rails.env}#{Date.today.to_s}.log", "daily")
# config.logger.level = Logger::INFO
# config.assets.prefix = '/dev-assets'
# Raises error for missing translations

View File

@ -0,0 +1,9 @@
require 'multi_logger'
formatter = Proc.new{|severity, time, progname, msg|
formatted_severity = sprintf("%-5s",severity.to_s)
formatted_time = time.strftime("%Y-%m-%d %H:%M:%S")
# "[#{formatted_severity} #{formatted_time} #{$$}] #{msg.to_s.strip}\n"
"#{msg.to_s.strip}\n"
}
MultiLogger.add_logger('user_trace', formatter: formatter, shift_age: 'daily')
Rails.logger.user_trace.level = Logger::INFO

View File

@ -16,9 +16,22 @@ Rails.application.routes.draw do
resources :edu_settings
scope '/api' do
get 'wallets/balance'
get 'wallets/coin_changes'
get 'log/file_list'
post 'log/download'
resources :sponsor_tiers
resources :sponsorships
resources :sponsorships do
collection do
get :sponsored
get :sponsoring
get :stopped_sponsored
get :stopped_sponsoring
get :stopped
end
end
resources :sync_forge, only: [:create] do
collection do

38
config/schedule.rb Normal file
View File

@ -0,0 +1,38 @@
# Use this file to easily define all of your cron jobs.
#
# It's helpful, but not entirely necessary to understand cron before proceeding.
# http://en.wikipedia.org/wiki/Cron
# Example:
#
# set :output, "/path/to/my/cron_log.log"
#
# every 2.hours do
# command "/usr/bin/some_great_command"
# runner "MyModel.some_method"
# rake "some:great:rake:task"
# end
#
# every 4.days do
# runner "AnotherModel.prune_old_records"
# end
# Learn more: http://github.com/javan/whenever
#
set :environment, :development
every '0 10 20 * *' do
runner 'Sponsorship.monthly_payment'
end
# every 1.month, at: 'January 20th 10:00am' do
# runner 'Sponsorship.monthly_payment'
# end
# #######################################################
# * * * * * command to be executed
# - - - - -
# | | | | |
# | | | | +----- day of week (0 - 6) (Sunday=0)
# | | | +------- month (1 - 12)
# | | +--------- day of month (1 - 31)
# | +----------- hour (0 - 23)
# +------------- min (0 - 59)
# #######################################################

View File

@ -0,0 +1,5 @@
class AddVisibleToStoppedSponsorship < ActiveRecord::Migration[5.2]
def change
add_column :stopped_sponsorships, :visible, :integer
end
end

View File

@ -0,0 +1,6 @@
class ChangeUserDescriptionType < ActiveRecord::Migration[5.2]
def change
remove_column :users, :description
add_column :users, :description, :text
end
end

View File

@ -0,0 +1,6 @@
class AddAccumulateToSponsorships < ActiveRecord::Migration[5.2]
def change
add_column :sponsorships, :accumulate, :integer, default: 0
add_column :stopped_sponsorships, :accumulate, :integer, default: 0
end
end

View File

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe LogController, type: :controller do
end

View File

@ -0,0 +1,12 @@
require 'rails_helper'
RSpec.describe WalletsController, type: :controller do
describe "GET #balance" do
it "returns http success" do
get :balance
expect(response).to have_http_status(:success)
end
end
end

View File

@ -0,0 +1,15 @@
require 'rails_helper'
# Specs in this file have access to a helper object that includes
# the LogHelper. For example:
#
# describe LogHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# expect(helper.concat_strings("this","that")).to eq("this that")
# end
# end
# end
RSpec.describe LogHelper, type: :helper do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -0,0 +1,15 @@
require 'rails_helper'
# Specs in this file have access to a helper object that includes
# the WalletsHelper. For example:
#
# describe WalletsHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# expect(helper.concat_strings("this","that")).to eq("this that")
# end
# end
# end
RSpec.describe WalletsHelper, type: :helper do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe "wallets/balance.html.erb", type: :view do
pending "add some examples to (or delete) #{__FILE__}"
end