diff --git a/app/controllers/operator/jobs_controller.rb b/app/controllers/operator/jobs_controller.rb index baccbe0..530e640 100644 --- a/app/controllers/operator/jobs_controller.rb +++ b/app/controllers/operator/jobs_controller.rb @@ -22,8 +22,7 @@ class Operator::JobsController < ApplicationController def create @job = Job.new(job_params) @job.created_by_operator = true - # TODO: rename costumer to creater? When created by operator the operator is referenced instead of costumer. - @job.costumer = current_user + @job.creator = current_user respond_to do |format| if @job.save @@ -40,6 +39,8 @@ class Operator::JobsController < ApplicationController def update @job.assign_attributes(job_params) @status_changed = @job.status_changed? + @job.current_user = current_user if @status_changed + respond_to do |format| if @job.save broadcast_update_job diff --git a/app/models/job.rb b/app/models/job.rb index 12bf803..9d951c8 100644 --- a/app/models/job.rb +++ b/app/models/job.rb @@ -1,6 +1,10 @@ class Job < ApplicationRecord - belongs_to :operator, class_name: "User", optional: true, counter_cache: :jobs_as_operator_count - belongs_to :costumer, class_name: "User", optional: true, counter_cache: :jobs_as_costumer_count + attr_accessor :current_user + + belongs_to :costumer, class_name: "User", optional: true, counter_cache: :jobs_as_costumer_count, inverse_of: :jobs_as_costumer + belongs_to :operator, class_name: "User", optional: true, counter_cache: :jobs_as_operator_count, inverse_of: :jobs_as_operator + belongs_to :creator, class_name: "User", optional: true, counter_cache: :created_jobs_count, inverse_of: :created_jobs + belongs_to :cashier, class_name: "User", optional: true, counter_cache: :cashed_jobs_count, inverse_of: :cashed_jobs has_one_attached :pdf, dependent: :purge @@ -11,11 +15,12 @@ class Job < ApplicationRecord validate :acceptable_pdf - before_save :update_printed_at, if: :will_save_change_to_status? - before_save :update_paid_at, if: :will_save_change_to_status? before_save :update_status_changed_at, if: :will_save_change_to_status? + before_save :update_user_status_infos, if: :will_save_change_to_status? + before_save :set_cost_qm before_save :calc_cost, if: :printed_pages_changes? + before_validation :set_costumer_infos, unless: :created_by_operator?, on: :create # TODO: works only when job is created. Should move analyzer to activestorage : @@ -36,6 +41,10 @@ class Job < ApplicationRecord AVAILABLE_PAGE_FORMATS = [ :a0, :a1, :a2, :a3 ] + # scope :created_as_operator, -> { where created_as_operator: true } + # scope :created_as_costumer, -> { where created_as_operator: false } + scope :not_canceled, -> { !canceled } + # NOTE: only named status are returned because of WHERE/IN clause for the enum values scope :in_status_order, -> { in_order_of(:status, %w[open printing pickup paid canceled]) } @@ -51,6 +60,8 @@ class Job < ApplicationRecord scope :status_changed_on_day, lambda { |date| where("status_changed_at >= ? AND status_changed_at <= ?", date.beginning_of_day, date.end_of_day) } + scope :created_by_costumer, -> { not(:created_by_operator) } + # Returns all jobs with status: open print pickup and jobs from today with status: paid canceled # paid: only updated_at today # canceled: only updated_at today @@ -111,19 +122,18 @@ class Job < ApplicationRecord end def self.report_to_csv(jobs) - columns = [ "id", "costumer_firstname", "costumer_lastname", "paid_at", "cost" ] - columns_readable = [ "ID", "Name", "Nachname", "bezahlt am", "Betrag" ] + columns_readable = [ "ID", "Kunde Vorname", "Kunde Nachname", "Kassierer Vorname", "Kassierer Nachname", "bezahlt am", "Betrag" ] CSV.generate(col_sep: ";") do |csv| csv << columns_readable jobs.each do |job| # csv << job.attributes.values_at(*columns) - csv << [ job.id, job.costumer_firstname, job.costumer_lastname, job.paid_at.localtime.strftime("%Y-%m-%d"), job.cost.to_s + " €" ] + csv << [ job.id, job.costumer_firstname, job.costumer_lastname, job.cashier_firstname, job.cashier_lastname, job.paid_at.localtime.strftime("%Y-%m-%d"), job.cost.to_s + " €" ] end end end def self.ransackable_attributes(auth_object = nil) - [ "created_at", "id", "costumer_firstname", "costumer_lastname", "pdf.", "number_of_plans_a0", "number_of_plans_a1", "number_of_plans_a2", "number_of_plans_a3", "costum_qm_plan", "cost", "status" ] + [ "created_at", "id", "costumer_firstname", "costumer_lastname", "pdf.", "created_by_operator", "number_of_plans_a0", "number_of_plans_a1", "number_of_plans_a2", "number_of_plans_a3", "costum_qm_plan", "cost", "status" ] end def self.ransackable_associations(auth_object = nil) @@ -136,14 +146,6 @@ class Job < ApplicationRecord costum_qm_plan_changed? || number_of_plans_a0_changed? || number_of_plans_a1_changed? || number_of_plans_a2_changed? || number_of_plans_a3_changed? end - def update_printed_at - self.printed_at = Time.now if pickup? || (paid? && printed_at.nil?) - end - - def update_paid_at - self.paid_at = Time.now if paid? - end - def update_status_changed_at self.status_changed_at = Time.now end @@ -186,7 +188,67 @@ class Job < ApplicationRecord end def set_costumer_infos + self.costumer = current_user unless self.costumer self.costumer_firstname = costumer.firstname self.costumer_lastname = costumer.lastname end + + def set_operator_infos + self.operator = current_user unless self.operator + self.operator_firstname = operator.firstname + self.operator_lastname = operator.lastname + end + + def clear_operator_infos + self.operator = nil + self.operator_firstname = nil + self.operator_lastname = nil + end + + def set_cashier_infos + self.paid_at = Time.now + self.cashier = current_user unless self.cashier + self.cashier_firstname = cashier.firstname + self.cashier_lastname = cashier.lastname + end + + def clear_cashier_infos + self.paid_at = nil + self.cashier = nil + self.cashier_firstname = nil + self.cashier_lastname = nil + end + + + def reset_operator_and_cashier_infos + clear_operator_infos + clear_cashier_infos + end + + def update_user_status_infos + if status_changed? + case status.to_sym + when :open + reset_operator_and_cashier_infos + self.printed_at = nil + self.paid_at = nil + when :printing + clear_cashier_infos + set_operator_infos + self.printed_at = nil + when :pickup + clear_cashier_infos + self.printed_at = Time.now unless self.printed_at + when :paid + set_operator_infos unless self.operator + self.printed_at = Time.now unless self.printed_at + set_cashier_infos unless self.cashier + self.paid_at = Time.now unless self.paid_at + end + end + end + + def reset_to_status_open? + status_changed? && open? + end end diff --git a/app/models/user.rb b/app/models/user.rb index 372e9f5..50db51e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,7 +1,10 @@ class User < ApplicationRecord has_secure_password + # has_many :jobs has_many :jobs_as_costumer, foreign_key: :costumer_id, class_name: "Job" has_many :jobs_as_operator, foreign_key: :operator_id, class_name: "Job" + has_many :created_jobs, foreign_key: :creator_id, class_name: "Job" + has_many :cashed_jobs, foreign_key: :cashier_id, class_name: "Job" generates_token_for :email_verification, expires_in: 2.days do email diff --git a/app/views/admin/jobs/_job_tr.html.erb b/app/views/admin/jobs/_job_tr.html.erb index abe168c..f12d6e4 100644 --- a/app/views/admin/jobs/_job_tr.html.erb +++ b/app/views/admin/jobs/_job_tr.html.erb @@ -44,11 +44,20 @@ <%= l job.created_at.localtime.to_date %>
<%= user.email %>
E-Mail Verifiziert: - <%= icon bool_icon(user.verified), class: "icon #{user.verified ? "text-green-600" : "text-red-600"}" %> -
<%= user.created_at %>
- + <%= icon bool_icon(user.verified), class: "icon #{user.verified ? "text-green-600" : "text-red-600"}" %> +<%= user.created_at %>
+Druckaufträge als Kunde: <%= @user.jobs_as_costumer.size %>
+davon abgebrochen: <%= @user.jobs_as_cosutmer.canceled.size %>
+Druckaufträge als Operator: <%= @user.jobs_as_operator.size %>
+Druckaufträge kassiert: <%= @user.cashed_jobs.size %>
+ diff --git a/app/views/admin/users/_user_tr.html.erb b/app/views/admin/users/_user_tr.html.erb index 59bd372..ca63780 100644 --- a/app/views/admin/users/_user_tr.html.erb +++ b/app/views/admin/users/_user_tr.html.erb @@ -18,7 +18,7 @@ <%= highlight user.email, [params.dig(:q, :firstname_or_lastname_or_email_cont).to_s, params.dig(:q, :email_start).to_s] %>Some Stats: -
- Operator ID: - <% if job.operator %> - <%= link_to_if allowed_to?(:show, job.operator, namespace: :Admin), "#{job.operatorr_id} - #{job.operator.name} (#{job.operator.email})", admin_user_path(job.operator) %> + Costumer ID: + <% if job.costumer %> + <%= link_to_if allowed_to?(:show?, job.costumer, namespace: :Admin), "#{job.costumer_id} - #{job.costumer.name} (#{job.costumer.email})", admin_user_path(job.costumer) %> <% else %> - <% end %>
- Costumer ID: - <% if job.costumer %> - <%= link_to_if allowed_to?(:show, job.costumer, namespace: :Admin), "#{job.costumer_id} - #{job.costumer.name} (#{job.costumer.email})", admin_user_path(job.costumer) %> + Creator ID: + <% if job.creator %> + <%= link_to_if allowed_to?(:show?, job.creator, namespace: :Admin, ), "#{job.creator_id} - #{job.creator.name} (#{job.creator.email})", admin_user_path(job.creator) %> <% else %> - <% end %>
++ Operator ID: + <% if job.operator %> + <%= link_to_if allowed_to?(:show?, job.operator, namespace: :Admin), "#{job.operator_id} - #{job.operator.name} (#{job.operator.email})", admin_user_path(job.operator) %> + <% else %> + - + <% end %> +
++ Cashier ID: + <% if job.cashier %> + <%= link_to_if allowed_to?(:show?, job.cashier, namespace: :Admin), "#{job.cashier_id} - #{job.cashier.name} (#{job.cashier.email})", admin_user_path(job.cashier) %> + <% else %> + - + <% end %> +
++ Kunde: + <%= link_to_if job.costumer && allowed_to?(:show? , job.costumer, namespace: :Admin), "#{job.costumer_firstname} #{job.costumer_lastname}", admin_user_path(job.costumer) %> +
Opertator: <%= link_to_if job.operator && allowed_to?(:show, job.operator, namespace: :Admin), "#{job.operator_firstname} #{job.operator_lastname}", admin_users_path(job.operator) %>
++ Kassierer: + <%= link_to_if job.cashier && allowed_to?(:show, job.cashier, namespace: :Admin), "#{job.cashier_firstname} #{job.cashier_lastname}", admin_users_path(job.cashier) %> +
Erstellt durch Opertator: <%= icon bool_icon(job.created_by_operator), class: "icon #{job.created_by_operator ? "text-green-600" : "text-red-600"}" %>
-- Auftraggeber: - <%= link_to_if job.costumer && !job.created_by_operator && allowed_to?(:show? , job.costumer, namespace: :Admin), "#{job.costumer_firstname} #{job.costumer_lastname}", admin_user_path(job.costumer) %> -
Aktueller Status: - <%= %> + + <%= job.status %> +
Paid at: diff --git a/db/migrate/20240727101347_create_jobs.rb b/db/migrate/20240727101347_create_jobs.rb index 05ce13a..e21cf4d 100644 --- a/db/migrate/20240727101347_create_jobs.rb +++ b/db/migrate/20240727101347_create_jobs.rb @@ -1,17 +1,19 @@ class CreateJobs < ActiveRecord::Migration[7.1] def change create_table :jobs do |t| - t.references :operator, null: true t.references :costumer, null: true - t.string :operator_firstname - t.string :operator_lastname + t.references :creator, null: true + t.references :cashier, null: true + t.references :operator, null: true t.string :costumer_firstname t.string :costumer_lastname - t.boolean :printed, default: false - t.boolean :paid, default: false + t.string :operator_firstname + t.string :operator_lastname + t.string :cashier_firstname + t.string :cashier_lastname t.datetime :printed_at - t.datetime :status_changed_at t.datetime :paid_at + t.datetime :status_changed_at t.boolean :intern, default: false t.string :cost_center t.string :status, default: "open", index: true diff --git a/db/migrate/20240826144015_create_users.rb b/db/migrate/20240826144015_create_users.rb index 3d6cb30..6d9002f 100644 --- a/db/migrate/20240826144015_create_users.rb +++ b/db/migrate/20240826144015_create_users.rb @@ -12,10 +12,14 @@ class CreateUsers < ActiveRecord::Migration[7.2] t.integer :jobs_as_costumer_count, default: 0 t.integer :jobs_as_operator_count, default: 0 + t.integer :created_jobs_count, default: 0 + t.integer :cashed_jobs_count, default: 0 t.timestamps end - add_foreign_key :jobs, :users, column: :operator_id add_foreign_key :jobs, :users, column: :costumer_id + add_foreign_key :jobs, :users, column: :operator_id + add_foreign_key :jobs, :users, column: :creator_id + add_foreign_key :jobs, :users, column: :cashier_id end end diff --git a/db/schema.rb b/db/schema.rb index 4ac030a..d0f4e11 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -40,17 +40,19 @@ ActiveRecord::Schema[7.2].define(version: 2024_08_26_144016) do end create_table "jobs", force: :cascade do |t| - t.integer "operator_id" t.integer "costumer_id" - t.string "operator_firstname" - t.string "operator_lastname" + t.integer "creator_id" + t.integer "cashier_id" + t.integer "operator_id" t.string "costumer_firstname" t.string "costumer_lastname" - t.boolean "printed", default: false - t.boolean "paid", default: false + t.string "operator_firstname" + t.string "operator_lastname" + t.string "cashier_firstname" + t.string "cashier_lastname" t.datetime "printed_at" - t.datetime "status_changed_at" t.datetime "paid_at" + t.datetime "status_changed_at" t.boolean "intern", default: false t.string "cost_center" t.string "status", default: "open" @@ -65,7 +67,9 @@ ActiveRecord::Schema[7.2].define(version: 2024_08_26_144016) do t.boolean "created_by_operator", default: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.index ["cashier_id"], name: "index_jobs_on_cashier_id" t.index ["costumer_id"], name: "index_jobs_on_costumer_id" + t.index ["creator_id"], name: "index_jobs_on_creator_id" t.index ["operator_id"], name: "index_jobs_on_operator_id" t.index ["status"], name: "index_jobs_on_status" end @@ -88,6 +92,8 @@ ActiveRecord::Schema[7.2].define(version: 2024_08_26_144016) do t.boolean "verified", default: false, null: false t.integer "jobs_as_costumer_count", default: 0 t.integer "jobs_as_operator_count", default: 0 + t.integer "created_jobs_count", default: 0 + t.integer "cashed_jobs_count", default: 0 t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["email"], name: "index_users_on_email", unique: true @@ -96,7 +102,9 @@ ActiveRecord::Schema[7.2].define(version: 2024_08_26_144016) do add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" + add_foreign_key "jobs", "users", column: "cashier_id" add_foreign_key "jobs", "users", column: "costumer_id" + add_foreign_key "jobs", "users", column: "creator_id" add_foreign_key "jobs", "users", column: "operator_id" add_foreign_key "sessions", "users" end diff --git a/db/seeds.rb b/db/seeds.rb index 5d8af9c..0143f8e 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -15,8 +15,9 @@ User.create!(email: "david.boehm@hs-rm.de", firstname: "David", lastname: "Böhm User.create!(email: "maximilian.lasser@hs-rm.de", firstname: "Max", lastname: "Lasser", role: :admin, password_digest: BCrypt::Password.create("admin"), verified: true) # Operators -User.create!(email: "tutor.operator@hs-rm.de", firstname: "Tutor", lastname: "Operator", role: :operator, password_digest: BCrypt::Password.create("operator"), verified: true) -User.create!(email: "tutor2.operator@hs-rm.de", firstname: "Tutor2", lastname: "Operator", role: :operator, password_digest: BCrypt::Password.create("operator"), verified: true) +operators = [] +operators << User.create!(email: "tutor.operator@hs-rm.de", firstname: "Tutor", lastname: "Operator", role: :operator, password_digest: BCrypt::Password.create("operator"), verified: true) +operators << User.create!(email: "tutor2.operator@hs-rm.de", firstname: "Tutor2", lastname: "Operator", role: :operator, password_digest: BCrypt::Password.create("operator"), verified: true) # Students User.create!(email: "stud.student@student.hs-rm.de", firstname: "Student", lastname: "Student", password_digest: BCrypt::Password.create("stud"), verified: true) @@ -54,7 +55,7 @@ end # created_at = Faker::Time.between_dates(from: Date.today - 60, to: Date.today, period: :day) email="#{firstname}.#{lastname}@student.hs-rm.de".downcase.gsub('ö', 'oe').gsub('ä', 'ae').gsub('ü', 'ue').gsub('ß', 'ss') email.delete(" ") - user=User.new(email: email, firstname: firstname, lastname: lastname, password_digest: BCrypt::Password.create("password"), verified: false, created_at: created_at).save! + User.new(email: email, firstname: firstname, lastname: lastname, password_digest: BCrypt::Password.create("password"), verified: false, created_at: created_at).save! end # Jobs paid (and some canceled) in the far past @@ -76,7 +77,12 @@ end end job = Job.new(status:, privacy_policy: true, created_at: created_at) job.pdf = File.open(Rails.root.join('db/pdfs/', pdf)) - job.costumer = students[rand(0...9)] + student = students[rand(0..9)] + job.costumer = student + job.creator = student + operator = operators[rand(0...1)] + job.operator = operator if status != :open + job.cashier = operator if status == :paid job.save! job.update_column :printed_at, printed_at # write with update_column to avoid before_save action job.update_column :status_changed_at, status_changed_at # write with update_column to avoid before_save action @@ -105,7 +111,12 @@ end end job = Job.new(status:, privacy_policy: true, created_at: created_at) job.pdf = File.open(Rails.root.join('db/pdfs/', pdf)) - job.costumer = students[rand(0...9)] + student = students[rand(0...9)] + job.costumer = student + job.creator = student + operator = operators[rand(0...1)] + job.operator = operator if status == :paid + job.cashier = operator if status == :paid job.save! job.update_column :printed_at, printed_at # write with update_column to avoid before_save action job.update_column :status_changed_at, status_changed_at # write with update_column to avoid before_save action @@ -125,7 +136,28 @@ end status = :open if i > 0 job = Job.new(status:, privacy_policy: true) job.pdf = File.open(Rails.root.join('db/pdfs/', pdf)) - job.costumer = students[rand(0...4)] + student = students[rand(0...4)] + job.costumer = student + job.creator = student + operator = operators[rand(0...1)] + job.operator = operator if status != :open + job.cashier = operator if status == :paid job.save! end end + +# Jobs created from operator +[ 'GanzWichtig.pdf', 'IchBinIn5MinDran.pdf', 'DerPlanDerImmerProblemeMacht.pdf', +'DieFarbenGefallenMirNicht.pdf', 'MachHinIchHabsEilig.pdf', 'WarumDauertDasSoLange.pdf', +'DenPlanBezahleIchNicht.pdf', 'IchWarAlsErstesDran.pdf', 'WarumIstDerPlotterDefekt.pdf', +'DasNächsteMalGeheIchWoAndersHin.pdf' ].shuffle.each do |pdf| + job = Job.new(privacy_policy: true) + job.pdf = File.open(Rails.root.join('db/pdfs/', pdf)) + job.costumer = students[rand(0...9)] + job.costumer_firstname = job.costumer.firstname + job.costumer_lastname = job.costumer.lastname + job.creator = operators[rand(0...1)] + job.created_by_operator = true + job.inspect + job.save! +end