├── log └── .keep ├── .ruby-version ├── app ├── mailers │ ├── .keep │ └── req_mailer.rb ├── models │ ├── .keep │ ├── concerns │ │ └── .keep │ ├── client.rb │ ├── users_role.rb │ ├── role.rb │ ├── history.rb │ ├── inf_workgroup_member.rb │ ├── unit.rb │ ├── assignment.rb │ ├── org_structure.rb │ ├── user.rb │ ├── req_workgroup.rb │ └── req_rolepurchase.rb ├── assets │ ├── images │ │ ├── .keep │ │ ├── a4.jpg │ │ ├── .DS_Store │ │ ├── rails.png │ │ ├── profile_small.jpg │ │ └── patterns │ │ │ ├── shattered.png │ │ │ ├── otis_redding.png │ │ │ ├── header-profile.png │ │ │ ├── header-profile-skin-1.png │ │ │ ├── header-profile-skin-2.png │ │ │ └── header-profile-skin-3.png │ ├── stylesheets │ │ ├── base │ │ │ ├── mixins.scss │ │ │ ├── custom.scss │ │ │ ├── typography.scss │ │ │ ├── variables.scss │ │ │ ├── badgets_labels.scss │ │ │ ├── metismenu.scss │ │ │ ├── theme-config.scss │ │ │ ├── chat.scss │ │ │ ├── media.scss │ │ │ └── top_navigation.scss │ │ ├── mystyle.scss │ │ ├── application.css │ │ ├── bootstrap_and_overrides.css.less │ │ └── style.scss │ ├── .DS_Store │ └── javascripts │ │ ├── bootstrap.js.coffee │ │ ├── assignments.coffee │ │ ├── req_purchases.coffee │ │ ├── req_reassigns.coffee │ │ ├── static_pages.coffee │ │ └── application.js ├── controllers │ ├── concerns │ │ └── .keep │ ├── static_pages_controller.rb │ ├── assignments_controller.rb │ ├── application_controller.rb │ ├── users_controller.rb │ ├── reports_controller.rb │ ├── req_workgroups_controller.rb │ ├── req_reassigns_controller.rb │ ├── req_rolepurchases_controller.rb │ └── req_purchases_controller.rb ├── views │ ├── .DS_Store │ ├── layouts │ │ ├── _messages.html.erb │ │ ├── _footer.html.erb │ │ ├── _topnavbar.html.erb │ │ ├── application.html.erb │ │ └── _nav.html.erb │ ├── shared │ │ ├── _actions_and_assignees.html.erb │ │ ├── _req_edit_buttons.html.erb │ │ ├── _error_messages.html.erb │ │ └── _history_tab.html.erb │ ├── devise │ │ ├── mailer │ │ │ ├── confirmation_instructions.html.erb │ │ │ ├── unlock_instructions.html.erb │ │ │ └── reset_password_instructions.html.erb │ │ ├── passwords │ │ │ ├── new.html.erb │ │ │ └── edit.html.erb │ │ ├── unlocks │ │ │ └── new.html.erb │ │ ├── confirmations │ │ │ └── new.html.erb │ │ ├── sessions │ │ │ └── new.html.erb │ │ ├── registrations │ │ │ ├── new.html.erb │ │ │ └── edit.html.erb │ │ └── shared │ │ │ └── _links.html.erb │ ├── req_mailer │ │ └── new_assignment_notification.html.erb │ ├── users │ │ ├── _users_role_fields.html.erb │ │ ├── edit.html.erb │ │ └── index.html.erb │ ├── req_workgroups │ │ ├── _inf_workgroup_member_fields.html.erb │ │ ├── new.html.erb │ │ ├── edit.html.erb │ │ └── index.html.erb │ ├── req_purchases │ │ ├── _edit_myfile.html.erb │ │ ├── new.html.erb │ │ ├── edit.html.erb │ │ ├── show.html.erb │ │ └── index.html.erb │ ├── req_rolepurchases │ │ ├── new.html.erb │ │ ├── edit.html.erb │ │ ├── show.html.erb │ │ └── index.html.erb │ ├── req_reassigns │ │ ├── new.html.erb │ │ ├── edit.html.erb │ │ ├── show.html.erb │ │ └── index.html.erb │ ├── reports │ │ └── index.html.erb │ └── assignments │ │ └── index.html.erb ├── inputs │ └── currency_input.rb ├── helpers │ ├── application_helper.rb │ └── req_helper.rb ├── policies │ ├── user_policy.rb │ └── application_policy.rb └── uploaders │ └── myfile_uploader.rb ├── lib ├── assets │ └── .keep ├── tasks │ ├── .keep │ ├── state_machine.rake │ └── state_machine.rb ├── capistrano │ ├── tasks │ │ ├── restart.cap │ │ ├── monit.cap │ │ ├── logs.cap │ │ ├── compile_assets_locally.cap │ │ ├── check_revision.cap │ │ ├── run_tests.cap │ │ ├── nginx.cap │ │ └── setup_config.cap │ ├── substitute_strings.rb │ └── template.rb ├── templates │ └── erb │ │ └── scaffold │ │ └── _form.html.erb └── req_main.rb ├── public ├── favicon.ico ├── robots.txt ├── 500.html ├── 422.html └── 404.html ├── vendor └── assets │ ├── javascripts │ ├── .keep │ └── metisMenu │ │ └── jquery.metisMenu.js │ └── stylesheets │ └── .keep ├── .rspec ├── .DS_Store ├── db ├── .DS_Store ├── migrate │ ├── .DS_Store │ ├── 20150726141353_add_name_to_users.rb │ ├── 20151025132756_add_myfile_to_req_purchases.rb │ ├── 20151107195223_add_admin_field_to_users.rb │ ├── 20151112193023_create_roles.rb │ ├── 20150809123847_create_clients.rb │ ├── 20151112193305_create_users_roles.rb │ ├── 20151104150102_add_unit_fields_to_users.rb │ ├── 20150915200001_create_req_purchases.rb │ ├── 20151214210051_add_fields_to_assignments.rb │ ├── 20151129000001_create_req_rolepurchases.rb │ ├── 20151014000001_create_req_workgroups.rb │ ├── 20150915201703_create_histories.rb │ ├── 20150817194216_create_assignments.rb │ ├── 20151014000002_create_inf_workgroup_members.rb │ ├── 20150915200002_create_req_reassigns.rb │ ├── 20151102195901_create_units.rb │ └── 20150515202844_devise_create_users.rb └── import │ ├── UsersImport.csv │ └── OgrStructureImport.csv ├── spec ├── .DS_Store ├── factories │ ├── units.rb │ ├── users_roles.rb │ ├── roles.rb │ └── users.rb ├── models │ ├── unit_spec.rb │ └── req_purchase_spec.rb ├── support │ ├── factory_girl.rb │ └── database_cleaner.rb ├── features │ └── user_login_and_logout_spec.rb └── rails_helper.rb ├── config ├── .DS_Store ├── boot.rb ├── initializers │ ├── cookies_serializer.rb │ ├── session_store.rb │ ├── mime_types.rb │ ├── filter_parameter_logging.rb │ ├── backtrace_silencers.rb │ ├── assets.rb │ ├── wrap_parameters.rb │ └── inflections.rb ├── environment.rb ├── unicorn.rb ├── locales │ ├── en.bootstrap.yml │ └── simple_form.en.yml ├── secrets.yml ├── deploy │ ├── shared │ │ ├── secrets.yml.erb │ │ ├── unicorn_init.sh.erb │ │ └── database.yml.erb │ ├── staging.rb │ └── production.rb ├── application.rb ├── environments │ ├── development.rb │ ├── test.rb │ └── production.rb ├── routes.rb ├── deploy.rb └── database.yml ├── ReqReassign_state.png ├── bin ├── bundle ├── rake ├── rails ├── rspec ├── spring └── setup ├── config.ru ├── Rakefile ├── .gitignore ├── Capfile ├── Gemfile └── README.md /log/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.1.4 -------------------------------------------------------------------------------- /app/mailers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/models/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/tasks/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/images/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vendor/assets/javascripts/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vendor/assets/stylesheets/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/stylesheets/base/mixins.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --require spec_helper 3 | -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klishevich/bpm/HEAD/.DS_Store -------------------------------------------------------------------------------- /db/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klishevich/bpm/HEAD/db/.DS_Store -------------------------------------------------------------------------------- /spec/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klishevich/bpm/HEAD/spec/.DS_Store -------------------------------------------------------------------------------- /config/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klishevich/bpm/HEAD/config/.DS_Store -------------------------------------------------------------------------------- /app/views/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klishevich/bpm/HEAD/app/views/.DS_Store -------------------------------------------------------------------------------- /lib/tasks/state_machine.rake: -------------------------------------------------------------------------------- 1 | require File.join("#{File.dirname(__FILE__)}/state_machine") -------------------------------------------------------------------------------- /ReqReassign_state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klishevich/bpm/HEAD/ReqReassign_state.png -------------------------------------------------------------------------------- /app/assets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klishevich/bpm/HEAD/app/assets/.DS_Store -------------------------------------------------------------------------------- /db/migrate/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klishevich/bpm/HEAD/db/migrate/.DS_Store -------------------------------------------------------------------------------- /app/assets/images/a4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klishevich/bpm/HEAD/app/assets/images/a4.jpg -------------------------------------------------------------------------------- /app/assets/images/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klishevich/bpm/HEAD/app/assets/images/.DS_Store -------------------------------------------------------------------------------- /app/assets/images/rails.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klishevich/bpm/HEAD/app/assets/images/rails.png -------------------------------------------------------------------------------- /app/models/client.rb: -------------------------------------------------------------------------------- 1 | class Client < ActiveRecord::Base 2 | belongs_to :manager, class_name: "User" 3 | end 4 | -------------------------------------------------------------------------------- /app/assets/images/profile_small.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klishevich/bpm/HEAD/app/assets/images/profile_small.jpg -------------------------------------------------------------------------------- /app/models/users_role.rb: -------------------------------------------------------------------------------- 1 | class UsersRole < ActiveRecord::Base 2 | belongs_to :user 3 | belongs_to :role 4 | end 5 | -------------------------------------------------------------------------------- /app/assets/images/patterns/shattered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klishevich/bpm/HEAD/app/assets/images/patterns/shattered.png -------------------------------------------------------------------------------- /app/models/role.rb: -------------------------------------------------------------------------------- 1 | class Role < ActiveRecord::Base 2 | has_many :users_roles 3 | has_many :users, through: :users_roles 4 | end 5 | -------------------------------------------------------------------------------- /spec/factories/units.rb: -------------------------------------------------------------------------------- 1 | FactoryGirl.define do 2 | factory :unit do 3 | name "MyString" 4 | level 1 5 | end 6 | 7 | end 8 | -------------------------------------------------------------------------------- /app/assets/images/patterns/otis_redding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klishevich/bpm/HEAD/app/assets/images/patterns/otis_redding.png -------------------------------------------------------------------------------- /spec/factories/users_roles.rb: -------------------------------------------------------------------------------- 1 | FactoryGirl.define do 2 | factory :users_role do 3 | user nil 4 | role nil 5 | end 6 | 7 | end 8 | -------------------------------------------------------------------------------- /app/assets/images/patterns/header-profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klishevich/bpm/HEAD/app/assets/images/patterns/header-profile.png -------------------------------------------------------------------------------- /app/controllers/static_pages_controller.rb: -------------------------------------------------------------------------------- 1 | class StaticPagesController < ApplicationController 2 | 3 | def home 4 | end 5 | 6 | end 7 | -------------------------------------------------------------------------------- /app/models/history.rb: -------------------------------------------------------------------------------- 1 | class History < ActiveRecord::Base 2 | belongs_to :historyable, polymorphic: true 3 | belongs_to :user 4 | end 5 | -------------------------------------------------------------------------------- /spec/factories/roles.rb: -------------------------------------------------------------------------------- 1 | FactoryGirl.define do 2 | factory :role do 3 | name "MyString" 4 | code "MyString" 5 | end 6 | 7 | end 8 | -------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /app/assets/images/patterns/header-profile-skin-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klishevich/bpm/HEAD/app/assets/images/patterns/header-profile-skin-1.png -------------------------------------------------------------------------------- /app/assets/images/patterns/header-profile-skin-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klishevich/bpm/HEAD/app/assets/images/patterns/header-profile-skin-2.png -------------------------------------------------------------------------------- /app/assets/images/patterns/header-profile-skin-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/klishevich/bpm/HEAD/app/assets/images/patterns/header-profile-skin-3.png -------------------------------------------------------------------------------- /app/assets/javascripts/bootstrap.js.coffee: -------------------------------------------------------------------------------- 1 | jQuery -> 2 | $("a[rel~=popover], .has-popover").popover() 3 | $("a[rel~=tooltip], .has-tooltip").tooltip() 4 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 2 | 3 | require 'bundler/setup' # Set up gems listed in the Gemfile. 4 | -------------------------------------------------------------------------------- /spec/models/unit_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | RSpec.describe Unit, type: :model do 4 | pending "add some examples to (or delete) #{__FILE__}" 5 | end 6 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require ::File.expand_path('../config/environment', __FILE__) 4 | run Rails.application 5 | -------------------------------------------------------------------------------- /db/migrate/20150726141353_add_name_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddNameToUsers < ActiveRecord::Migration 2 | def change 3 | add_column :users, :name, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.action_dispatch.cookies_serializer = :json 4 | -------------------------------------------------------------------------------- /config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.session_store :cookie_store, key: '_bpm_session' 4 | -------------------------------------------------------------------------------- /spec/models/req_purchase_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | RSpec.describe ReqPurchase, type: :model do 4 | pending "add some examples to (or delete) #{__FILE__}" 5 | end 6 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require File.expand_path('../application', __FILE__) 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /db/migrate/20151025132756_add_myfile_to_req_purchases.rb: -------------------------------------------------------------------------------- 1 | class AddMyfileToReqPurchases < ActiveRecord::Migration 2 | def change 3 | add_column :req_purchases, :myfile, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/views/layouts/_messages.html.erb: -------------------------------------------------------------------------------- 1 | <% flash.each do |key, value| %> 2 |
3 | × 4 | <%= value %> 5 |
6 | <% end %> -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | begin 3 | load File.expand_path("../spring", __FILE__) 4 | rescue LoadError 5 | end 6 | require_relative '../config/boot' 7 | require 'rake' 8 | Rake.application.run 9 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /db/migrate/20151107195223_add_admin_field_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddAdminFieldToUsers < ActiveRecord::Migration 2 | def change 3 | add_column :users, :admin, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/views/shared/_actions_and_assignees.html.erb: -------------------------------------------------------------------------------- 1 |

На статусе доступны следующие действия: <%= @req.state_events.join(", ") %>

2 |

Текущее назначение: <%= @req.opened_assignment_users %>

-------------------------------------------------------------------------------- /app/models/inf_workgroup_member.rb: -------------------------------------------------------------------------------- 1 | class InfWorkgroupMember < ActiveRecord::Base 2 | belongs_to :req_workgroup 3 | belongs_to :user 4 | 5 | validates :req_workgroup, presence: true 6 | validates :user, presence: true 7 | end -------------------------------------------------------------------------------- /app/models/unit.rb: -------------------------------------------------------------------------------- 1 | class Unit < ActiveRecord::Base 2 | belongs_to :manager, class_name: "User" 3 | belongs_to :parent, class_name: "Unit" 4 | has_many :children, foreign_key: "parent_id", class_name: "Unit" 5 | 6 | end 7 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | # User-agent: * 5 | # Disallow: / 6 | -------------------------------------------------------------------------------- /app/controllers/assignments_controller.rb: -------------------------------------------------------------------------------- 1 | class AssignmentsController < ApplicationController 2 | # before_action :authenticate_user! 3 | def index 4 | @assignments = Assignment.where(user_id: current_user.id).order('id desc') 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/views/layouts/_footer.html.erb: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | begin 3 | load File.expand_path("../spring", __FILE__) 4 | rescue LoadError 5 | end 6 | APP_PATH = File.expand_path('../../config/application', __FILE__) 7 | require_relative '../config/boot' 8 | require 'rails/commands' 9 | -------------------------------------------------------------------------------- /app/assets/javascripts/assignments.coffee: -------------------------------------------------------------------------------- 1 | # Place all the behaviors and hooks related to the matching controller here. 2 | # All this logic will automatically be available in application.js. 3 | # You can use CoffeeScript in this file: http://coffeescript.org/ 4 | -------------------------------------------------------------------------------- /app/assets/javascripts/req_purchases.coffee: -------------------------------------------------------------------------------- 1 | # Place all the behaviors and hooks related to the matching controller here. 2 | # All this logic will automatically be available in application.js. 3 | # You can use CoffeeScript in this file: http://coffeescript.org/ 4 | -------------------------------------------------------------------------------- /app/assets/javascripts/req_reassigns.coffee: -------------------------------------------------------------------------------- 1 | # Place all the behaviors and hooks related to the matching controller here. 2 | # All this logic will automatically be available in application.js. 3 | # You can use CoffeeScript in this file: http://coffeescript.org/ 4 | -------------------------------------------------------------------------------- /app/assets/javascripts/static_pages.coffee: -------------------------------------------------------------------------------- 1 | # Place all the behaviors and hooks related to the matching controller here. 2 | # All this logic will automatically be available in application.js. 3 | # You can use CoffeeScript in this file: http://coffeescript.org/ 4 | -------------------------------------------------------------------------------- /db/migrate/20151112193023_create_roles.rb: -------------------------------------------------------------------------------- 1 | class CreateRoles < ActiveRecord::Migration 2 | def change 3 | create_table :roles do |t| 4 | t.string :name 5 | t.string :code 6 | 7 | t.timestamps null: false 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/views/devise/mailer/confirmation_instructions.html.erb: -------------------------------------------------------------------------------- 1 |

Welcome <%= @email %>!

2 | 3 |

You can confirm your account email through the link below:

4 | 5 |

<%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %>

6 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require File.expand_path('../config/application', __FILE__) 5 | 6 | Rails.application.load_tasks 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/views/req_mailer/new_assignment_notification.html.erb: -------------------------------------------------------------------------------- 1 |

Уважаемый <%=@assignment.user.name %>, для вас было создано новое задание: <%=@assignment.description %>

2 |

Чтобы посмотреть подробную информацию перейдите по ссылке - <%= link_to "перейти к заданию", @assignment.assignable %>

-------------------------------------------------------------------------------- /app/inputs/currency_input.rb: -------------------------------------------------------------------------------- 1 | class CurrencyInput < SimpleForm::Inputs::Base 2 | def input(wrapper_options) 3 | merged_input_options = merge_wrapper_options(input_html_options, wrapper_options) 4 | 5 | "$ #{@builder.text_field(attribute_name, merged_input_options)}".html_safe 6 | end 7 | end -------------------------------------------------------------------------------- /app/views/shared/_req_edit_buttons.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= link_to "Отмена", @req, class: "btn btn-white"%> 3 | <%= f.submit :save, class: "btn btn-primary"%> 4 | <% @req.state_events.each do |x| %> 5 | <%= f.submit x, class: "btn btn-primary"%> 6 | <% end %> 7 |
-------------------------------------------------------------------------------- /spec/factories/users.rb: -------------------------------------------------------------------------------- 1 | FactoryGirl.define do 2 | factory :user do 3 | email "someone@example.tld" 4 | name "Mike" 5 | password "somepassword" 6 | end 7 | end 8 | 9 | # email: "someone@example.tld", name: "Mike", 10 | # password: "somepassword", password_confirmation: "somepassword" -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | def is_active_controller?(controller_name) 3 | params[:controller] == controller_name ? "active" : nil 4 | end 5 | 6 | def is_active_action?(action_name) 7 | params[:action] == action_name ? "active" : nil 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20150809123847_create_clients.rb: -------------------------------------------------------------------------------- 1 | class CreateClients < ActiveRecord::Migration 2 | def change 3 | create_table :clients do |t| 4 | t.string :name 5 | t.string :inn 6 | t.references :manager, references: :users 7 | 8 | t.timestamps null: false 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/models/assignment.rb: -------------------------------------------------------------------------------- 1 | class Assignment < ActiveRecord::Base 2 | belongs_to :user 3 | belongs_to :assignable, polymorphic: true 4 | after_create :send_new_assignment_notification 5 | 6 | private 7 | 8 | def send_new_assignment_notification 9 | ReqMailer.new_assignment_notification(self).deliver_now 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/assets/stylesheets/base/custom.scss: -------------------------------------------------------------------------------- 1 | /* Only demo */ 2 | @media (max-width: 1000px) { 3 | .welcome-message { 4 | display: none; 5 | } 6 | } 7 | 8 | .lightBoxGallery { 9 | text-align: center; 10 | } 11 | 12 | .lightBoxGallery img { 13 | margin: 5px; 14 | } 15 | 16 | /*.footer { 17 | position: relative; 18 | }*/ -------------------------------------------------------------------------------- /app/views/devise/mailer/unlock_instructions.html.erb: -------------------------------------------------------------------------------- 1 |

Hello <%= @resource.email %>!

2 | 3 |

Your account has been locked due to an excessive number of unsuccessful sign in attempts.

4 | 5 |

Click the link below to unlock your account:

6 | 7 |

<%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %>

8 | -------------------------------------------------------------------------------- /db/migrate/20151112193305_create_users_roles.rb: -------------------------------------------------------------------------------- 1 | class CreateUsersRoles < ActiveRecord::Migration 2 | def change 3 | create_table :users_roles do |t| 4 | t.references :user, index: true, foreign_key: true 5 | t.references :role, index: true, foreign_key: true 6 | 7 | t.timestamps null: false 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/policies/user_policy.rb: -------------------------------------------------------------------------------- 1 | class UserPolicy < ApplicationPolicy 2 | 3 | def index? 4 | user.admin? 5 | end 6 | 7 | def show? 8 | user.admin? 9 | end 10 | 11 | def create? 12 | user.admin? 13 | end 14 | 15 | def update? 16 | user.admin? 17 | end 18 | 19 | def destroy? 20 | user.admin? 21 | end 22 | 23 | end -------------------------------------------------------------------------------- /spec/support/factory_girl.rb: -------------------------------------------------------------------------------- 1 | RSpec.configure do |config| 2 | config.include FactoryGirl::Syntax::Methods 3 | 4 | config.before(:suite) do 5 | begin 6 | DatabaseCleaner.start 7 | # Test factories in spec/factories are working. 8 | FactoryGirl.lint 9 | ensure 10 | DatabaseCleaner.clean 11 | end 12 | end 13 | 14 | end -------------------------------------------------------------------------------- /db/migrate/20151104150102_add_unit_fields_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddUnitFieldsToUsers < ActiveRecord::Migration 2 | def change 3 | add_reference :users, :unit, index: true, foreign_key: true 4 | add_column :users, :code, :string 5 | add_column :users, :unit_code, :string 6 | add_column :users, :deleted, :boolean, default: false 7 | 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/capistrano/tasks/restart.cap: -------------------------------------------------------------------------------- 1 | namespace :deploy do 2 | desc 'Commands for unicorn application' 3 | %w(start stop force-stop restart upgrade reopen-logs).each do |command| 4 | task command.to_sym do 5 | on roles(:app), in: :sequence, wait: 5 do 6 | "/etc/init.d/unicorn_#{fetch(:full_app_name)} #{command}" 7 | end 8 | end 9 | end 10 | end -------------------------------------------------------------------------------- /app/views/users/_users_role_fields.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 | <%= link_to_remove_association "Удалить", f, class: "btn btn-warning" %> 4 |
5 |
6 | <%= f.input :role_id, collection: Role.order(:name).all, label_method: :name, value_method: :id, label: false %> 7 |
8 |

9 |
-------------------------------------------------------------------------------- /db/migrate/20150915200001_create_req_purchases.rb: -------------------------------------------------------------------------------- 1 | class CreateReqPurchases < ActiveRecord::Migration 2 | def change 3 | create_table :req_purchases do |t| 4 | t.string :state, :default => 'new' 5 | t.integer :last_user_id, index: true 6 | t.string :name 7 | t.timestamps null: false 8 | 9 | t.integer :money 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20151214210051_add_fields_to_assignments.rb: -------------------------------------------------------------------------------- 1 | class AddFieldsToAssignments < ActiveRecord::Migration 2 | def change 3 | add_column :assignments, :close_date, :datetime 4 | add_column :assignments, :deadline_date, :datetime 5 | add_column :assignments, :notify_before_date, :datetime 6 | add_column :assignments, :notify_after_date, :datetime 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20151129000001_create_req_rolepurchases.rb: -------------------------------------------------------------------------------- 1 | class CreateReqRolepurchases < ActiveRecord::Migration 2 | def change 3 | create_table :req_rolepurchases do |t| 4 | t.string :state, :default => 'new' 5 | t.integer :last_user_id, index: true 6 | t.string :name 7 | t.timestamps null: false 8 | 9 | t.integer :money 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/models/org_structure.rb: -------------------------------------------------------------------------------- 1 | class OrgStructure 2 | def self.get_chief(user_email) 3 | User.where(email: user_email).first.unit.manager.email 4 | # if (user_email == 'manager1@test.co') 5 | # u = 'chief1@test.co' 6 | # elsif (["manager2@test.co", "manager22@test.co"].include? user_email) 7 | # u = 'chief2@test.co' 8 | # else 9 | # u = "ceo@test.co" 10 | # end 11 | end 12 | end -------------------------------------------------------------------------------- /app/assets/stylesheets/mystyle.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the Assignments controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: http://sass-lang.com/ 4 | .fl1 { 5 | float:left; 6 | margin-right: 5px; 7 | } 8 | 9 | .rheader{ 10 | padding-bottom: 10px; 11 | } 12 | 13 | .alert { 14 | background: lightyellow; 15 | color: #8a6d3b; 16 | } -------------------------------------------------------------------------------- /db/migrate/20151014000001_create_req_workgroups.rb: -------------------------------------------------------------------------------- 1 | class CreateReqWorkgroups < ActiveRecord::Migration 2 | def change 3 | create_table :req_workgroups do |t| 4 | t.string :state, :default => 'new' 5 | t.integer :last_user_id, index: true 6 | t.string :name 7 | t.timestamps null: false 8 | 9 | t.integer :money 10 | t.string :description 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20150915201703_create_histories.rb: -------------------------------------------------------------------------------- 1 | class CreateHistories < ActiveRecord::Migration 2 | def change 3 | create_table :histories do |t| 4 | t.references :historyable, polymorphic: true, index: true 5 | t.string :state 6 | t.references :user, index: true, foreign_key: true 7 | t.text :description 8 | t.text :new_values 9 | 10 | t.timestamps null: false 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /bin/rspec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # This file was generated by Bundler. 4 | # 5 | # The application 'rspec' is installed as part of a gem, and 6 | # this file is here to facilitate running it. 7 | # 8 | 9 | require 'pathname' 10 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile", 11 | Pathname.new(__FILE__).realpath) 12 | 13 | require 'rubygems' 14 | require 'bundler/setup' 15 | 16 | load Gem.bin_path('rspec-core', 'rspec') 17 | -------------------------------------------------------------------------------- /lib/templates/erb/scaffold/_form.html.erb: -------------------------------------------------------------------------------- 1 | <%%= simple_form_for(@<%= singular_table_name %>) do |f| %> 2 | <%%= f.error_notification %> 3 | 4 |
5 | <%- attributes.each do |attribute| -%> 6 | <%%= f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %> %> 7 | <%- end -%> 8 |
9 | 10 |
11 | <%%= f.button :submit %> 12 |
13 | <%% end %> 14 | -------------------------------------------------------------------------------- /db/migrate/20150817194216_create_assignments.rb: -------------------------------------------------------------------------------- 1 | class CreateAssignments < ActiveRecord::Migration 2 | def change 3 | create_table :assignments do |t| 4 | t.references :user, index: true, foreign_key: true 5 | t.references :assignable, polymorphic: true, index: true 6 | t.string :description 7 | t.boolean :closed, default: false 8 | t.string :result 9 | t.timestamps null: false 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20151014000002_create_inf_workgroup_members.rb: -------------------------------------------------------------------------------- 1 | class CreateInfWorkgroupMembers < ActiveRecord::Migration 2 | def change 3 | create_table :inf_workgroup_members do |t| 4 | t.references :req_workgroup, index: true, foreign_key: true 5 | t.references :user, index: true, foreign_key: true 6 | t.boolean :main, default: false 7 | t.string :comment 8 | t.timestamps null: false 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /lib/capistrano/tasks/monit.cap: -------------------------------------------------------------------------------- 1 | namespace :monit do 2 | %w(start stop restart).each do |task_name| 3 | desc "#{task_name} Monit" 4 | task task_name do 5 | on roles(:app), in: :sequence, wait: 5 do 6 | sudo "service monit #{task_name}" 7 | end 8 | end 9 | end 10 | 11 | desc "Reload Monit" 12 | task 'reload' do 13 | on roles(:app), in: :sequence, wait: 5 do 14 | sudo "monit reload" 15 | end 16 | end 17 | end -------------------------------------------------------------------------------- /lib/capistrano/substitute_strings.rb: -------------------------------------------------------------------------------- 1 | # we often want to refer to variables which 2 | # are defined in subsequent stage files. This 3 | # let's us use the {{var}} to represent fetch(:var) 4 | # in strings which are only evaluated at runtime. 5 | 6 | def sub_strings(input_string) 7 | output_string = input_string 8 | input_string.scan(/{{(\w*)}}/).each do |var| 9 | output_string.gsub!("{{#{var[0]}}}", fetch(var[0].to_sym)) 10 | end 11 | output_string 12 | end -------------------------------------------------------------------------------- /app/views/devise/mailer/reset_password_instructions.html.erb: -------------------------------------------------------------------------------- 1 |

Hello <%= @resource.email %>!

2 | 3 |

Someone has requested a link to change your password. You can do this through the link below.

4 | 5 |

<%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %>

6 | 7 |

If you didn't request this, please ignore this email.

8 |

Your password won't change until you access the link above and create a new one.

9 | -------------------------------------------------------------------------------- /app/assets/stylesheets/base/typography.scss: -------------------------------------------------------------------------------- 1 | h1, h2, h3, h4, h5, h6 { 2 | font-weight: 100; 3 | } 4 | 5 | h1 { 6 | font-size: 30px; 7 | } 8 | 9 | h2 { 10 | font-size: 24px; 11 | } 12 | 13 | h3 { 14 | font-size: 16px; 15 | } 16 | 17 | h4 { 18 | font-size: 14px; 19 | } 20 | 21 | h5 { 22 | font-size: 12px; 23 | } 24 | 25 | h6 { 26 | font-size: 10px; 27 | } 28 | 29 | h3, h4, h5 { 30 | margin-top: 5px; 31 | font-weight: 600; 32 | } 33 | -------------------------------------------------------------------------------- /app/views/shared/_error_messages.html.erb: -------------------------------------------------------------------------------- 1 | <% if object.errors.any? %> 2 |
3 |
4 | 5 | <%= object.errors.count %> <%= "error".pluralize(object.errors.count) %> 6 |
7 | 12 |
13 | <% end %> -------------------------------------------------------------------------------- /config/unicorn.rb: -------------------------------------------------------------------------------- 1 | root = "/home/mike/apps/bpm_production/current" 2 | working_directory root 3 | pid "#{root}/tmp/pids/unicorn.pid" 4 | stderr_path "#{root}/log/unicorn.log" 5 | stdout_path "#{root}/log/unicorn.log" 6 | 7 | listen "/tmp/unicorn.bpm_production.sock" 8 | worker_processes 2 9 | timeout 30 10 | 11 | # Force the bundler gemfile environment variable to 12 | # reference the capistrano "current" symlink 13 | before_exec do |_| 14 | ENV["BUNDLE_GEMFILE"] = File.join(root, 'Gemfile') 15 | end -------------------------------------------------------------------------------- /lib/capistrano/tasks/logs.cap: -------------------------------------------------------------------------------- 1 | namespace :logs do 2 | task :tail, :file do |t, args| 3 | if args[:file] 4 | on roles(:app) do 5 | execute "tail -f #{shared_path}/log/#{args[:file]}.log" 6 | end 7 | else 8 | puts "please specify a logfile e.g: 'rake logs:tail[logfile]" 9 | puts "will tail 'shared_path/log/logfile.log'" 10 | puts "remember if you use zsh you'll need to format it as:" 11 | puts "rake 'logs:tail[logfile]' (single quotes)" 12 | end 13 | end 14 | end -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | 10 | # Ignore all logfiles and tempfiles. 11 | /log/* 12 | !/log/.keep 13 | /tmp 14 | /public/system 15 | /public/myfiles 16 | /public/uploads 17 | -------------------------------------------------------------------------------- /app/mailers/req_mailer.rb: -------------------------------------------------------------------------------- 1 | class ReqMailer < ActionMailer::Base 2 | default from: "no-reply@bpm.j123.ru" 3 | 4 | def new_assignment_notification(assignment) 5 | @assignment = assignment 6 | Rails.logger.debug 'test_email' 7 | mail to: "m.klishevich@yandex.ru, #{@assignment.user.email}", subject: t(:new_req) 8 | end 9 | 10 | # def test_email1 11 | # Rails.logger.debug 'test_email' 12 | # mail(:to => 'm.klishevich@yandex.ru', :subject => "testing rails", body: "lasfkasf") 13 | # end 14 | 15 | end 16 | -------------------------------------------------------------------------------- /app/views/devise/passwords/new.html.erb: -------------------------------------------------------------------------------- 1 |

Forgot your password?

2 | 3 | <%= simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %> 4 | <%= f.error_notification %> 5 | 6 |
7 | <%= f.input :email, required: true, autofocus: true %> 8 |
9 | 10 |
11 | <%= f.button :submit, "Send me reset password instructions" %> 12 |
13 | <% end %> 14 | 15 | <%= render "devise/shared/links" %> 16 | -------------------------------------------------------------------------------- /bin/spring: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # This file loads spring without using Bundler, in order to be fast. 4 | # It gets overwritten when you run the `spring binstub` command. 5 | 6 | unless defined?(Spring) 7 | require "rubygems" 8 | require "bundler" 9 | 10 | if match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m) 11 | Gem.paths = { "GEM_PATH" => [Bundler.bundle_path.to_s, *Gem.path].uniq } 12 | gem "spring", match[1] 13 | require "spring/binstub" 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Version of your assets, change this if you want to expire all your assets. 4 | Rails.application.config.assets.version = '1.0' 5 | 6 | # Add additional assets to the asset load path 7 | # Rails.application.config.assets.paths << Emoji.images_path 8 | 9 | # Precompile additional assets. 10 | # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. 11 | # Rails.application.config.assets.precompile += %w( search.js ) 12 | -------------------------------------------------------------------------------- /app/views/devise/unlocks/new.html.erb: -------------------------------------------------------------------------------- 1 |

Resend unlock instructions

2 | 3 | <%= simple_form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %> 4 | <%= f.error_notification %> 5 | <%= f.full_error :unlock_token %> 6 | 7 |
8 | <%= f.input :email, required: true, autofocus: true %> 9 |
10 | 11 |
12 | <%= f.button :submit, "Resend unlock instructions" %> 13 |
14 | <% end %> 15 | 16 | <%= render "devise/shared/links" %> 17 | -------------------------------------------------------------------------------- /app/views/req_workgroups/_inf_workgroup_member_fields.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 | <%= link_to_remove_association "Удалить", f, class: "btn btn-warning" %> 4 |
5 |
6 | <%= f.input :user_id, collection: User.order(:name).all, label_method: :name, value_method: :id, label: false %> 7 |
8 |
9 | <%= f.input :main, as: :boolean %> 10 |
11 |
12 | <%= f.input :comment, label: false %> 13 |
14 |

15 |
-------------------------------------------------------------------------------- /app/helpers/req_helper.rb: -------------------------------------------------------------------------------- 1 | module ReqHelper 2 | def req_edit_header(h2, link, link_name, name) 3 | raw '
4 |
5 |

' + h2 + '

6 | 12 |
13 |
' 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /app/views/devise/confirmations/new.html.erb: -------------------------------------------------------------------------------- 1 |

Resend confirmation instructions

2 | 3 | <%= simple_form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %> 4 | <%= f.error_notification %> 5 | <%= f.full_error :confirmation_token %> 6 | 7 |
8 | <%= f.input :email, required: true, autofocus: true %> 9 |
10 | 11 |
12 | <%= f.button :submit, "Resend confirmation instructions" %> 13 |
14 | <% end %> 15 | 16 | <%= render "devise/shared/links" %> 17 | -------------------------------------------------------------------------------- /app/views/devise/sessions/new.html.erb: -------------------------------------------------------------------------------- 1 |

Вход

2 |
3 |
4 | <%= simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %> <%= f.input :email, required: false, autofocus: true %> 5 | <%= f.input :password, required: false, id: "password" %> 6 | <%= f.input :remember_me, as: :boolean if devise_mapping.rememberable? %> 7 | <%= f.button :submit, "Войти", id: "log_in", class: "btn btn-success" %> 8 | <% end %> 9 | 10 | <%= render "devise/shared/links" %> 11 |
12 |
13 | -------------------------------------------------------------------------------- /db/migrate/20150915200002_create_req_reassigns.rb: -------------------------------------------------------------------------------- 1 | class CreateReqReassigns < ActiveRecord::Migration 2 | def change 3 | create_table :req_reassigns do |t| 4 | t.string :state, :default => 'new' 5 | t.integer :last_user_id, index: true 6 | t.string :name 7 | t.timestamps null: false 8 | 9 | t.string :role 10 | t.integer :money 11 | t.integer :old_manager_id, index: true 12 | t.integer :new_manager_id, index: true 13 | t.references :client, index: true, foreign_key: true 14 | t.text :info 15 | 16 | end 17 | end 18 | end -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] if respond_to?(:wrap_parameters) 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /db/migrate/20151102195901_create_units.rb: -------------------------------------------------------------------------------- 1 | class CreateUnits < ActiveRecord::Migration 2 | def change 3 | create_table :units do |t| 4 | t.string :name 5 | t.string :code 6 | t.string :parent_code 7 | t.string :manager_code 8 | t.integer :level 9 | t.integer :parent_id, index: true 10 | t.integer :manager_id, index: true 11 | t.boolean :deleted, default: false 12 | 13 | t.timestamps null: false 14 | end 15 | add_foreign_key :units, :units, column: :parent_id 16 | add_foreign_key :units, :users, column: :manager_id 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/capistrano/tasks/compile_assets_locally.cap: -------------------------------------------------------------------------------- 1 | namespace :deploy do 2 | desc "compiles assets locally then rsyncs" 3 | task :compile_assets_locally do 4 | run_locally do 5 | execute "RAILS_ENV=#{fetch(:rails_env)} bundle exec rake assets:precompile" 6 | end 7 | on roles(:app) do |role| 8 | run_locally do 9 | execute"rsync -av ./public/assets/ #{role.user}@#{role.hostname}:#{release_path}/public/assets/;" 10 | end 11 | sudo "chmod -R 755 #{release_path}/public/assets/" 12 | end 13 | run_locally do 14 | execute "rm -rf ./public/assets" 15 | end 16 | end 17 | end -------------------------------------------------------------------------------- /lib/capistrano/tasks/check_revision.cap: -------------------------------------------------------------------------------- 1 | namespace :deploy do 2 | desc "checks whether the currently checkout out revision matches the 3 | remote one we're trying to deploy from" 4 | task :check_revision do 5 | branch = fetch(:branch) 6 | unless `git rev-parse HEAD` == `git rev-parse origin/#{branch}` 7 | puts "WARNING: HEAD is not the same as origin/#{branch}" 8 | puts "Run `git push` to sync changes or make sure you've" 9 | puts "checked out the branch: #{branch} as you can only deploy" 10 | puts "if you've got the target branch checked out" 11 | exit 12 | end 13 | end 14 | end -------------------------------------------------------------------------------- /lib/capistrano/tasks/run_tests.cap: -------------------------------------------------------------------------------- 1 | namespace :deploy do 2 | desc "Runs test before deploying, can't deploy unless they pass" 3 | task :run_tests do 4 | test_log = "log/capistrano.test.log" 5 | tests = fetch(:tests) 6 | tests.each do |test| 7 | puts "--> Running tests: '#{test}', please wait ..." 8 | unless system "bundle exec rspec #{test} > #{test_log} 2>&1" 9 | puts "--> Tests: '#{test}' failed. Results in: #{test_log} and below:" 10 | system "cat #{test_log}" 11 | exit; 12 | end 13 | puts "--> '#{test}' passed" 14 | end 15 | puts "--> All tests passed" 16 | system "rm #{test_log}" 17 | end 18 | end -------------------------------------------------------------------------------- /db/import/UsersImport.csv: -------------------------------------------------------------------------------- 1 | email;password;password_confirmation;name;code;unit_code 2 | manager1@test.co;testtest;testtest;Менеджер Один;m1;krasn_sales 3 | manager2@test.co;testtest;testtest;Менеджер Два;m2;novosib_sales 4 | manager22@test.co;testtest;testtest;Менеджер Двадцать Два;m22;novosib_sales 5 | chief1@test.co;testtest;testtest;Шеф Один;maks;krasn 6 | chief2@test.co;testtest;testtest;Шеф Два;alex;novosib 7 | ceo@test.co;testtest;testtest;Директор;mike;center 8 | admin@test.co;testtest;testtest;Админ;petr;center_dev 9 | ;;;;; 10 | ;;;;; 11 | ;;;;; 12 | ;;;;; 13 | ;;;;; 14 | ;;;;; 15 | ;;;;; 16 | ;;;;; 17 | ;;;;; 18 | ;;;;; 19 | ;;;;; 20 | ;;;;; 21 | ;;;;; 22 | ;;;;; -------------------------------------------------------------------------------- /lib/capistrano/tasks/nginx.cap: -------------------------------------------------------------------------------- 1 | namespace :nginx do 2 | %w(start stop restart reload).each do |task_name| 3 | desc "#{task } Nginx" 4 | task task_name do 5 | on roles(:app), in: :sequence, wait: 5 do 6 | sudo "/etc/init.d/nginx #{task_name}" 7 | end 8 | end 9 | end 10 | 11 | desc "Remove default Nginx Virtual Host" 12 | task "remove_default_vhost" do 13 | on roles(:app) do 14 | if test("[ -f /etc/nginx/sites-enabled/default ]") 15 | sudo "rm /etc/nginx/sites-enabled/default" 16 | puts "removed default Nginx Virtualhost" 17 | else 18 | puts "No default Nginx Virtualhost to remove" 19 | end 20 | end 21 | end 22 | end -------------------------------------------------------------------------------- /config/locales/en.bootstrap.yml: -------------------------------------------------------------------------------- 1 | # Sample localization file for English. Add more files in this directory for other locales. 2 | # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. 3 | 4 | en: 5 | breadcrumbs: 6 | application: 7 | root: "Index" 8 | pages: 9 | pages: "Pages" 10 | helpers: 11 | actions: "Actions" 12 | links: 13 | back: "Back" 14 | cancel: "Cancel" 15 | confirm: "Are you sure?" 16 | destroy: "Delete" 17 | new: "New" 18 | edit: "Edit" 19 | titles: 20 | edit: "Edit %{model}" 21 | save: "Save %{model}" 22 | new: "New %{model}" 23 | delete: "Delete %{model}" 24 | -------------------------------------------------------------------------------- /db/import/OgrStructureImport.csv: -------------------------------------------------------------------------------- 1 | name;code;parent_code;manager_code 2 | Центральный офис;center;;mike 3 | Бухгалтерия;center_buh;center;john 4 | Финансовая служба;center_fin;center;mike 5 | Служба безопасности;center_safe;center;leo 6 | Отдел разработки;center_dev;center;petr 7 | Отдел продаж;center_sales;center;ilia 8 | Филиал Красноярский;krasn;center;maks 9 | Отдел разработки;krasn_dev;krasn;maks 10 | Отдел продаж;krasn_sales;krasn;maks 11 | Филиал Новосибирский;novosib;center;alex 12 | Отдел разработки;novosib_dev;novosib;alex 13 | Отдел продаж;novosib_sales;novosib;alex 14 | Представительство в Кемерово;kemerovo;novosib;ivan 15 | Отдел продаж;kemerovo_sales;kemerovo;ivan 16 | ;;; 17 | ;;; -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | include Pundit 3 | 4 | protect_from_forgery with: :exception 5 | 6 | before_action :authenticate_user! 7 | 8 | before_action :configure_permitted_parameters, if: :devise_controller? 9 | 10 | # after_action :verify_authorized, :except => [:index , :home] 11 | rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized 12 | 13 | protected 14 | 15 | def configure_permitted_parameters 16 | devise_parameter_sanitizer.for(:sign_up) << :name 17 | end 18 | 19 | def user_not_authorized 20 | flash[:success] = t(:not_authorized) 21 | redirect_to root_path 22 | end 23 | 24 | end 25 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym 'RESTful' 16 | # end 17 | -------------------------------------------------------------------------------- /app/views/devise/passwords/edit.html.erb: -------------------------------------------------------------------------------- 1 |

Change your password

2 | 3 | <%= simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| %> 4 | <%= f.error_notification %> 5 | 6 | <%= f.input :reset_password_token, as: :hidden %> 7 | <%= f.full_error :reset_password_token %> 8 | 9 |
10 | <%= f.input :password, label: "New password", required: true, autofocus: true %> 11 | <%= f.input :password_confirmation, label: "Confirm your new password", required: true %> 12 |
13 | 14 |
15 | <%= f.button :submit, "Change my password" %> 16 |
17 | <% end %> 18 | 19 | <%= render "devise/shared/links" %> 20 | -------------------------------------------------------------------------------- /app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, 6 | * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the top of the 9 | * compiled file, but it's generally better to create a new file per style scope. 10 | * 11 | *= require_self 12 | *= require font-awesome 13 | *= require animate/animate.css 14 | *= require style 15 | *= require datepicker 16 | *= require mystyle 17 | */ 18 | -------------------------------------------------------------------------------- /app/views/devise/registrations/new.html.erb: -------------------------------------------------------------------------------- 1 |

Регистрация

2 |
3 |
4 | <%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> 5 | <%= f.error_notification %> 6 | 7 |
8 | <%= f.input :email, required: true, autofocus: true %> 9 | <%= f.input :name, required: true %> 10 | <%= f.input :password, required: true, hint: ("#{@minimum_password_length} characters minimum" if @validatable) %> 11 | <%= f.input :password_confirmation, required: true %> 12 |
13 | 14 |
15 | <%= f.button :submit, "Зарегистрироваться", class: "btn btn-success"%> 16 |
17 | <% end %> 18 | 19 | <%= render "devise/shared/links" %> 20 |
21 |
22 | -------------------------------------------------------------------------------- /app/policies/application_policy.rb: -------------------------------------------------------------------------------- 1 | class ApplicationPolicy 2 | attr_reader :user, :record 3 | 4 | def initialize(user, record) 5 | @user = user 6 | @record = record 7 | end 8 | 9 | def index? 10 | false 11 | end 12 | 13 | def show? 14 | scope.where(:id => record.id).exists? 15 | end 16 | 17 | def create? 18 | false 19 | end 20 | 21 | def new? 22 | create? 23 | end 24 | 25 | def update? 26 | false 27 | end 28 | 29 | def edit? 30 | update? 31 | end 32 | 33 | def destroy? 34 | false 35 | end 36 | 37 | def scope 38 | Pundit.policy_scope!(user, record.class) 39 | end 40 | 41 | class Scope 42 | attr_reader :user, :scope 43 | 44 | def initialize(user, scope) 45 | @user = user 46 | @scope = scope 47 | end 48 | 49 | def resolve 50 | scope 51 | end 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /app/assets/javascripts/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, 5 | // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 8 | // compiled file. 9 | // 10 | // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details 11 | // about supported directives. 12 | // 13 | //= require jquery/jquery-2.1.1.js 14 | //= require jquery_ujs 15 | //= require bootstrap-sprockets 16 | //= require metisMenu/jquery.metisMenu.js 17 | //= require pace/pace.min.js 18 | //= require slimscroll/jquery.slimscroll.min.js 19 | //= require cocoon 20 | //= require_tree . 21 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'pathname' 3 | 4 | # path to your application root. 5 | APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) 6 | 7 | Dir.chdir APP_ROOT do 8 | # This script is a starting point to setup your application. 9 | # Add necessary setup steps to this file: 10 | 11 | puts "== Installing dependencies ==" 12 | system "gem install bundler --conservative" 13 | system "bundle check || bundle install" 14 | 15 | # puts "\n== Copying sample files ==" 16 | # unless File.exist?("config/database.yml") 17 | # system "cp config/database.yml.sample config/database.yml" 18 | # end 19 | 20 | puts "\n== Preparing database ==" 21 | system "bin/rake db:setup" 22 | 23 | puts "\n== Removing old logs and tempfiles ==" 24 | system "rm -f log/*" 25 | system "rm -rf tmp/cache" 26 | 27 | puts "\n== Restarting application server ==" 28 | system "touch tmp/restart.txt" 29 | end 30 | -------------------------------------------------------------------------------- /config/locales/simple_form.en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | simple_form: 3 | "yes": 'Yes' 4 | "no": 'No' 5 | required: 6 | text: 'required' 7 | mark: '*' 8 | # You can uncomment the line below if you need to overwrite the whole required html. 9 | # When using html, text and mark won't be used. 10 | # html: '*' 11 | error_notification: 12 | default_message: "Please review the problems below:" 13 | # Examples 14 | # labels: 15 | # defaults: 16 | # password: 'Password' 17 | # user: 18 | # new: 19 | # email: 'E-mail to sign in.' 20 | # edit: 21 | # email: 'E-mail.' 22 | # hints: 23 | # defaults: 24 | # username: 'User name to sign in.' 25 | # password: 'No special characters, please.' 26 | # include_blanks: 27 | # defaults: 28 | # age: 'Rather not say' 29 | # prompts: 30 | # defaults: 31 | # age: 'Select your age' 32 | -------------------------------------------------------------------------------- /config/secrets.yml: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Your secret key is used for verifying the integrity of signed cookies. 4 | # If you change this key, all old signed cookies will become invalid! 5 | 6 | # Make sure the secret is at least 30 characters and all random, 7 | # no regular words or you'll be exposed to dictionary attacks. 8 | # You can use `rake secret` to generate a secure secret key. 9 | 10 | # Make sure the secrets in this file are kept private 11 | # if you're sharing your code publicly. 12 | 13 | development: 14 | secret_key_base: 85afb000603e714ab553fba6b9e5caca6f40090b8dc4e2e239d9d374b81959b36b91cd41e5eec175d6f7d25d9cce53b9854e43fd35ed79978c1984f5cb760ea5 15 | 16 | test: 17 | secret_key_base: f500ca15ba3df7e3f77a724f32012affc9f105eaa618795ba4399617c1a7551b4b915291647b6b1db78ffdfee1d124f1c9163c057e44a86da670b8cd0df91c7c 18 | 19 | # Do not keep production secrets in the repository, 20 | # instead read values from the environment. 21 | production: 22 | secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> 23 | -------------------------------------------------------------------------------- /config/deploy/shared/secrets.yml.erb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Your secret key is used for verifying the integrity of signed cookies. 4 | # If you change this key, all old signed cookies will become invalid! 5 | 6 | # Make sure the secret is at least 30 characters and all random, 7 | # no regular words or you'll be exposed to dictionary attacks. 8 | # You can use `rake secret` to generate a secure secret key. 9 | 10 | # Make sure the secrets in this file are kept private 11 | # if you're sharing your code publicly. 12 | 13 | development: 14 | secret_key_base: 85afb000603e714ab553fba6b9e5caca6f40090b8dc4e2e239d9d374b81959b36b91cd41e5eec175d6f7d25d9cce53b9854e43fd35ed79978c1984f5cb760ea5 15 | 16 | test: 17 | secret_key_base: f500ca15ba3df7e3f77a724f32012affc9f105eaa618795ba4399617c1a7551b4b915291647b6b1db78ffdfee1d124f1c9163c057e44a86da670b8cd0df91c7c 18 | 19 | # Do not keep production secrets in the repository, 20 | # instead read values from the environment. 21 | production: 22 | secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> 23 | -------------------------------------------------------------------------------- /app/models/user.rb: -------------------------------------------------------------------------------- 1 | class User < ActiveRecord::Base 2 | # has_many :req_reassigns, dependent: :destroy 3 | has_many :clients, foreign_key: "manager_id", class_name: "Client", dependent: :destroy 4 | has_many :old_req_reassigns, foreign_key: "old_manager_id", class_name: "User" 5 | has_many :new_req_reassigns, foreign_key: "new_manager_id", class_name: "User" 6 | has_many :users_roles, dependent: :destroy 7 | accepts_nested_attributes_for :users_roles, allow_destroy: true, 8 | reject_if: proc { |attributes| attributes['role_id'].blank? } 9 | has_many :roles, through: :users_roles 10 | belongs_to :unit 11 | # Include default devise modules. Others available are: 12 | # :confirmable, :lockable, :timeoutable and :omniauthable 13 | devise :database_authenticatable, :registerable, 14 | :recoverable, :rememberable, :trackable, :validatable 15 | VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i 16 | validates :email, presence: true, format: {with: VALID_EMAIL_REGEX}, uniqueness: {case_sensitive: false} 17 | validates :name, presence: true 18 | end 19 | -------------------------------------------------------------------------------- /app/views/req_purchases/_edit_myfile.html.erb: -------------------------------------------------------------------------------- 1 | <% myfile_has_errors = @req.errors[:myfile].present? %> 2 | <% err_class_form_group = myfile_has_errors ? "has-error".html_safe : "".html_safe %> 3 | <% err_class_label = myfile_has_errors ? "error".html_safe : "".html_safe %> 4 |
5 | 6 |
7 | <% if @req.myfile? %> 8 | <% #link_to(@req.myfile_url.rpartition('/').last, @req.myfile.url)%> 9 | <%= link_to(@req.myfile_identifier, @req.myfile.url)%> 10 |
11 | <%= f.check_box :remove_myfile %> 12 | 13 | <% end %> 14 | <%= f.file_field :myfile %> 15 | <%= f.hidden_field :myfile_cache %> 16 | <% if myfile_has_errors %> 17 | <%= @req.errors[:myfile].first %> 18 | <% end %> 19 |
20 | <%# f.input :myfile, disabled: @req.is_disabled?("name") %> -------------------------------------------------------------------------------- /app/controllers/users_controller.rb: -------------------------------------------------------------------------------- 1 | class UsersController < ApplicationController 2 | 3 | def index 4 | @users = User.all.order('name') 5 | # authorize User 6 | end 7 | 8 | # def show 9 | # @user = User.find(params[:id]) 10 | # end 11 | 12 | def edit 13 | @user=User.find(params[:id]) 14 | authorize @user 15 | end 16 | 17 | def update 18 | @user = User.find(params[:id]) 19 | authorize @user 20 | if @user.update_attributes(user_params) 21 | flash[:success] = t(:updated_successfuly) 22 | redirect_to users_path 23 | else 24 | render 'edit' 25 | end 26 | end 27 | 28 | # def destroy 29 | # user = User.find(params[:id]) 30 | # unless user == current_user 31 | # user.destroy 32 | # redirect_to users_path, :notice => "User deleted." 33 | # else 34 | # redirect_to users_path, :notice => "Can't delete yourself." 35 | # end 36 | # end 37 | 38 | private 39 | 40 | def user_params 41 | params.require(:user).permit(:name, :code, :unit_id, :deleted, :admin, 42 | users_roles_attributes: [:id, :role_id, :user_id, :_destroy]) 43 | end 44 | 45 | end -------------------------------------------------------------------------------- /lib/capistrano/template.rb: -------------------------------------------------------------------------------- 1 | # will first try and copy the file: 2 | # config/deploy/#{full_app_name}/#{from}.erb 3 | # to: 4 | # shared/config/to 5 | # if the original source path doesn exist then it will 6 | # search in: 7 | # config/deploy/shared/#{from}.erb 8 | # this allows files which are common to all enviros to 9 | # come from a single source while allowing specific 10 | # ones to be over-ridden 11 | # if the target file name is the same as the source then 12 | # the second parameter can be left out 13 | def smart_template(from, to=nil) 14 | to ||= from 15 | full_to_path = "#{shared_path}/config/#{to}" 16 | if from_erb_path = template_file(from) 17 | from_erb = StringIO.new(ERB.new(File.read(from_erb_path)).result(binding)) 18 | upload! from_erb, full_to_path 19 | info "copying: #{from_erb} to: #{full_to_path}" 20 | else 21 | error "error #{from} not found" 22 | end 23 | end 24 | 25 | def template_file(name) 26 | if File.exist?((file = "config/deploy/#{fetch(:full_app_name)}/#{name}.erb")) 27 | return file 28 | elsif File.exist?((file = "config/deploy/shared/#{name}.erb")) 29 | return file 30 | end 31 | return nil 32 | end -------------------------------------------------------------------------------- /app/views/devise/registrations/edit.html.erb: -------------------------------------------------------------------------------- 1 |

Edit <%= resource_name.to_s.humanize %>

2 | 3 | <%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> 4 | <%= f.error_notification %> 5 | 6 |
7 | <%= f.input :email, required: true, autofocus: true %> 8 | 9 | <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> 10 |

Currently waiting confirmation for: <%= resource.unconfirmed_email %>

11 | <% end %> 12 | 13 | <%= f.input :password, autocomplete: "off", hint: "leave it blank if you don't want to change it", required: false %> 14 | <%= f.input :password_confirmation, required: false %> 15 | <%= f.input :current_password, hint: "we need your current password to confirm your changes", required: true %> 16 |
17 | 18 |
19 | <%= f.button :submit, "Update" %> 20 |
21 | <% end %> 22 | 23 |

Cancel my account

24 | 25 |

Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>

26 | 27 | <%= link_to "Back", :back %> 28 | -------------------------------------------------------------------------------- /app/views/layouts/_topnavbar.html.erb: -------------------------------------------------------------------------------- 1 |
2 | 22 |
-------------------------------------------------------------------------------- /Capfile: -------------------------------------------------------------------------------- 1 | # Load DSL and set up stages 2 | require 'capistrano/setup' 3 | 4 | # Include default deployment tasks 5 | require 'capistrano/deploy' 6 | 7 | require 'capistrano/rails' 8 | require 'capistrano/bundler' 9 | require 'capistrano/rvm' 10 | require 'capistrano/rails/assets' 11 | 12 | # Include tasks from other gems included in your Gemfile 13 | # 14 | # For documentation on these, see for example: 15 | # 16 | # https://github.com/capistrano/rvm 17 | # https://github.com/capistrano/rbenv 18 | # https://github.com/capistrano/chruby 19 | # https://github.com/capistrano/bundler 20 | # https://github.com/capistrano/rails 21 | # https://github.com/capistrano/passenger 22 | # 23 | # require 'capistrano/rvm' 24 | # require 'capistrano/rbenv' 25 | # require 'capistrano/chruby' 26 | # require 'capistrano/bundler' 27 | # require 'capistrano/rails/assets' 28 | # require 'capistrano/rails/migrations' 29 | # require 'capistrano/passenger' 30 | 31 | # Load custom tasks from `lib/capistrano/tasks` if you have any defined 32 | Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r } 33 | 34 | Dir.glob('lib/capistrano/tasks/*.cap').each { |r| import r } 35 | Dir.glob('lib/capistrano/**/*.rb').each { |r| import r } 36 | -------------------------------------------------------------------------------- /app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BPM on Rails 7 | 8 | 9 | <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> 10 | 11 | 12 | <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %> 13 | <%= csrf_meta_tags %> 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | <%= render 'layouts/navigation' %> 23 | 24 | 25 |
26 | 27 | 28 | <%= render 'layouts/topnavbar' %> 29 | 30 | 31 | <%= render 'layouts/messages' %> 32 | <%= yield %> 33 | 34 | 35 | <%= render 'layouts/footer' %> 36 | 37 |
38 | 39 | 40 |
41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /app/controllers/reports_controller.rb: -------------------------------------------------------------------------------- 1 | class ReportsController < ApplicationController 2 | 3 | def index 4 | end 5 | 6 | def sla 7 | @req_types = req_types 8 | @states = states 9 | @assignments = Assignment.all 10 | if params[:report_sla] 11 | @state = params[:report_sla][:state] 12 | @user_id = params[:report_sla][:user_id] 13 | @req_type = params[:report_sla][:req_type] 14 | @date_begin = params[:report_sla][:date_begin] 15 | @date_end = params[:report_sla][:date_end] 16 | end 17 | @assignments = @assignments.where(closed: true) if @state == 'closed' 18 | @assignments = @assignments.where(closed: false) if @state == 'opened' 19 | @assignments = @assignments.where(user_id: @user_id) if !@user_id.blank? 20 | @assignments = @assignments.where(assignable_type: @req_type) if !@req_type.blank? 21 | @assignments = @assignments.where("created_at >= ?", @date_begin) if !@date_begin.blank? 22 | @assignments = @assignments.where("created_at <= ?", @date_end) if !@date_end.blank? 23 | end 24 | 25 | private 26 | def req_types 27 | ['ReqReassign', 'ReqPurchase', 'ReqRolepurchase', 'ReqWorkgroup'] 28 | end 29 | 30 | def states 31 | [['Закрытые','closed'],['Открытые', 'opened']] 32 | end 33 | 34 | end 35 | -------------------------------------------------------------------------------- /app/views/devise/shared/_links.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%- if controller_name != 'sessions' %> 3 | <%= link_to "Вход", new_session_path(resource_name) %>
4 | <% end -%> 5 | 6 | <%- if devise_mapping.registerable? && controller_name != 'registrations' %> 7 | <%= link_to "Регистрация", new_registration_path(resource_name) %>
8 | <% end -%> 9 | 10 | <%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %> 11 | <%= link_to "Забыли пароль?", new_password_path(resource_name) %>
12 | <% end -%> 13 | 14 | <%- if devise_mapping.confirmable? && controller_name != 'confirmations' %> 15 | <%= link_to "Не получили подтверждение регистрации?", new_confirmation_path(resource_name) %>
16 | <% end -%> 17 | 18 | <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %> 19 | <%= link_to "Не получили инструкции по разблокировке?", new_unlock_path(resource_name) %>
20 | <% end -%> 21 | 22 | <%- if devise_mapping.omniauthable? %> 23 | <%- resource_class.omniauth_providers.each do |provider| %> 24 | <%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider) %>
25 | <% end -%> 26 | <% end -%> 27 | -------------------------------------------------------------------------------- /app/views/shared/_history_tab.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | <% @history.each do |h| %> 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | <% end %> 24 | 25 |
<%= History.human_attribute_name("created_at") %><%= History.human_attribute_name("user_id") %><%= History.human_attribute_name("state") %><%= History.human_attribute_name("description") %><%= History.human_attribute_name("new_values") %>
<%= h.created_at.strftime('%d.%m.%Y %T') %><%= h.user.name %><%= h.state %><%= h.description %><%= h.new_values %>
26 |
27 |
28 |
-------------------------------------------------------------------------------- /app/assets/stylesheets/bootstrap_and_overrides.css.less: -------------------------------------------------------------------------------- 1 | @import "twitter/bootstrap/bootstrap"; 2 | 3 | // Set the correct sprite paths 4 | @iconSpritePath: image-url("twitter/bootstrap/glyphicons-halflings.png"); 5 | @iconWhiteSpritePath: image-url("twitter/bootstrap/glyphicons-halflings-white.png"); 6 | 7 | // Set the Font Awesome (Font Awesome is default. You can disable by commenting below lines) 8 | @fontAwesomeEotPath: font-url("fontawesome-webfont.eot"); 9 | @fontAwesomeEotPath_iefix: font-url("fontawesome-webfont.eot?#iefix"); 10 | @fontAwesomeWoffPath: font-url("fontawesome-webfont.woff"); 11 | @fontAwesomeTtfPath: font-url("fontawesome-webfont.ttf"); 12 | @fontAwesomeSvgPath: font-url("fontawesome-webfont.svg#fontawesomeregular"); 13 | 14 | // Font Awesome 15 | @import "fontawesome/font-awesome"; 16 | 17 | // Glyphicons 18 | //@import "twitter/bootstrap/glyphicons.less"; 19 | 20 | // Your custom LESS stylesheets goes here 21 | // 22 | // Since bootstrap was imported above you have access to its mixins which 23 | // you may use and inherit here 24 | // 25 | // If you'd like to override bootstrap's own variables, you can do so here as well 26 | // See http://twitter.github.com/bootstrap/customize.html#variables for their names and documentation 27 | // 28 | // Example: 29 | // @link-color: #ff0000; 30 | -------------------------------------------------------------------------------- /app/assets/stylesheets/style.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * INSPINIA - Responsive Admin Theme 4 | * version 2.3 5 | * 6 | */ 7 | 8 | // Google Fonts 9 | @import url("https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700&lang=en"); 10 | 11 | // Bootstra 12 | @import "bootstrap-sprockets"; 13 | @import "bootstrap"; 14 | 15 | // Variables, Mixins 16 | @import "base/variables"; 17 | @import "base/mixins"; 18 | 19 | // INSPINIA Theme Elements 20 | @import "base/typography"; 21 | @import "base/navigation"; 22 | @import "base/top_navigation"; 23 | @import "base/buttons"; 24 | @import "base/badgets_labels"; 25 | @import "base/elements"; 26 | @import "base/sidebar"; 27 | @import "base/base"; 28 | @import "base/pages"; 29 | @import "base/chat"; 30 | @import "base/metismenu"; 31 | @import "base/spinners"; 32 | 33 | // Landing page 34 | @import "base/landing"; 35 | 36 | // RTL Support 37 | @import "base/rtl"; 38 | 39 | // For demo only - config box style 40 | @import "base/theme-config"; 41 | 42 | // INSPINIA Skins 43 | @import "base/skins"; 44 | @import "base/md-skin"; 45 | 46 | // Media query style 47 | @import "base/media"; 48 | 49 | // Custom style 50 | // Your custom style to override base style 51 | @import "base/custom"; 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /lib/capistrano/tasks/setup_config.cap: -------------------------------------------------------------------------------- 1 | namespace :deploy do 2 | task :setup_config do 3 | on roles(:app) do 4 | # make the config dir 5 | execute :mkdir, "-p #{shared_path}/config" 6 | full_app_name = fetch(:full_app_name) 7 | 8 | # config files to be uploaded to shared/config, see the 9 | # definition of smart_template for details of operation. 10 | # Essentially looks for #{filename}.erb in deploy/#{full_app_name}/ 11 | # and if it isn't there, falls back to deploy/#{shared}. Generally 12 | # everything should be in deploy/shared with params which differ 13 | # set in the stage files 14 | config_files = fetch(:config_files) 15 | config_files.each do |file| 16 | smart_template file 17 | end 18 | 19 | # which of the above files should be marked as executable 20 | executable_files = fetch(:executable_config_files) 21 | executable_files.each do |file| 22 | execute :chmod, "+x #{shared_path}/config/#{file}" 23 | end 24 | 25 | # symlink stuff which should be... symlinked 26 | symlinks = fetch(:symlinks) 27 | 28 | # symlinks.each do |symlink| 29 | # sudo "ln -nfs #{shared_path}/config/#{symlink[:source]} #{sub_strings(symlink[:link])}" 30 | # end 31 | end 32 | end 33 | end -------------------------------------------------------------------------------- /lib/tasks/state_machine.rb: -------------------------------------------------------------------------------- 1 | namespace :state_machine do 2 | desc 'Draws state machines using GraphViz (options: CLASS=User,Vehicle; FILE=user.rb,vehicle.rb [not required in Rails / Merb]; FONT=Arial; FORMAT=png; ORIENTATION=portrait; HUMAN_NAMES=true' 3 | task :draw do 4 | # Build drawing options 5 | options = {} 6 | options[:file] = ENV['FILE'] if ENV['FILE'] 7 | options[:path] = ENV['TARGET'] if ENV['TARGET'] 8 | options[:format] = ENV['FORMAT'] if ENV['FORMAT'] 9 | options[:font] = ENV['FONT'] if ENV['FONT'] 10 | options[:orientation] = ENV['ORIENTATION'] if ENV['ORIENTATION'] 11 | options[:human_names] = ENV['HUMAN_NAMES'] == 'true' if ENV['HUMAN_NAMES'] 12 | 13 | if defined?(Rails) 14 | puts "Files are automatically loaded in Rails; ignoring FILE option" if options.delete(:file) 15 | Rake::Task['environment'].invoke 16 | elsif defined?(Merb) 17 | puts "Files are automatically loaded in Merb; ignoring FILE option" if options.delete(:file) 18 | Rake::Task['merb_env'].invoke 19 | 20 | # Fix ruby-graphviz being incompatible with Merb's process title 21 | $0 = 'rake' 22 | else 23 | # Load the library 24 | $:.unshift(File.dirname(__FILE__) + '/..') 25 | require 'state_machine' 26 | end 27 | 28 | StateMachine::Machine.draw(ENV['CLASS'], options) 29 | end 30 | end -------------------------------------------------------------------------------- /app/views/req_rolepurchases/new.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Создать заявку на закупку (с ролями)

4 | 9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
Создание заявки на закупку
17 |
18 | 19 | 20 |
21 |
22 |
23 | <%= simple_form_for(@req) do |f| %> 24 | <%= f.input :name %> 25 | <%= f.input :money %> 26 |
27 | <%= link_to "Отмена", @req, class: "btn btn-white"%> 28 | <%= f.submit :save, class: "btn btn-primary"%> 29 |
30 | <% end %> 31 |
32 |
33 |
34 |
35 |
36 | 37 | -------------------------------------------------------------------------------- /app/views/req_workgroups/new.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Создать рабочую группу

4 | 9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
Создание рабочей группы
17 |
18 | 19 | 20 |
21 |
22 |
23 | <%= simple_form_for(@req) do |f| %> 24 | <%= f.input :name %> 25 | <%= f.input :description %> 26 | <%= f.input :money %> 27 |
28 | <%= link_to "Отмена", @req, class: "btn btn-white"%> 29 | <%= f.submit :save, class: "btn btn-primary"%> 30 |
31 | <% end %> 32 |
33 |
34 |
35 |
36 |
37 | 38 | -------------------------------------------------------------------------------- /app/views/req_purchases/new.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Создать заявку на закупку

4 | 9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
Создание заявки на закупку
17 |
18 | 19 | 20 |
21 |
22 |
23 | <%= simple_form_for(@req) do |f| %> 24 | <%= f.input :name %> 25 | <%= f.input :money %> 26 | <%= render 'edit_myfile', f: f %> 27 |
28 | <%= link_to "Отмена", @req, class: "btn btn-white"%> 29 | <%= f.submit :save, class: "btn btn-primary"%> 30 |
31 | <% end %> 32 |
33 |
34 |
35 |
36 |
37 | 38 | -------------------------------------------------------------------------------- /app/assets/stylesheets/base/variables.scss: -------------------------------------------------------------------------------- 1 | // Font 2 | $font-stack: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif; 3 | 4 | // Basic Colors 5 | $navy: #1ab394; // Primary color 6 | $dark-gray: #c2c2c2; // Default color 7 | $blue: #1c84c6; // Success color 8 | $lazur: #23c6c8; // Info color 9 | $yellow: #f8ac59; // Warrning color 10 | $red: #ed5565; // Danger color 11 | 12 | // Various colors 13 | $text-color: #676a6c; // Body text 14 | $gray: #f3f3f4; // Background wrapper color 15 | $light-gray: #d1dade; // Default label, badget 16 | $label-badget-color: #5e5e5e; 17 | $light-blue: #f3f6fb; 18 | 19 | // Spiner color and margin 20 | $spin-color: $navy; 21 | $spin-margin: 0 auto; 22 | 23 | // IBOX colors ( default panel colors) 24 | $border-color: #e7eaec; // IBox border 25 | $ibox-title-bg: white; // IBox Background header 26 | $ibox-content-bg: white; // IBox Background content 27 | 28 | //Sidebar width 29 | $sidebar-width: 220px; 30 | 31 | // Boxed layout width 32 | $boxed-width: 1200px; 33 | $boxed-backgound: image-url("patterns/shattered.png"); 34 | 35 | //Border radius for buttons 36 | $btn-border-radius: 3px; 37 | 38 | //Navigation 39 | $nav-bg: #2f4050; 40 | $nav-profil-pattern: image-url("patterns/header-profile.png") no-repeat; 41 | $nav-text-color: #a7b1c2; 42 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' 4 | gem 'rails', '4.2.1' 5 | gem 'bootstrap-sass', '~> 3.3.5' 6 | gem 'font-awesome-rails', '4.3.0.0' 7 | gem 'pg' 8 | gem 'sass-rails', '~> 5.0' 9 | gem 'uglifier', '>= 1.3.0' 10 | gem 'coffee-rails', '~> 4.1.0' 11 | gem 'jquery-rails' 12 | gem 'turbolinks' 13 | gem 'jbuilder', '~> 2.0' 14 | gem 'sdoc', '~> 0.4.0', group: :doc 15 | gem 'state_machines-activerecord' 16 | # gem 'ruby-graphviz', :require => 'graphviz' 17 | gem 'simple_form' 18 | gem 'rails-i18n', '~> 4.0.0' # For 4.0.x 19 | gem 'capistrano', '~> 3.1', require: false 20 | gem 'capistrano-rails', '~> 1.1', require: false 21 | gem 'capistrano-bundler', '~> 1.1', require: false 22 | gem 'capistrano-rvm', '~> 0.1', require: false 23 | gem 'unicorn' 24 | gem 'devise' 25 | gem 'factory_girl_rails', '~> 4.5' 26 | gem 'capybara' 27 | gem "cocoon" 28 | # gem "paperclip", "~> 4.3" 29 | gem 'carrierwave' 30 | gem 'pundit' 31 | gem 'telegram-bot-ruby' 32 | 33 | group :development, :test do 34 | end 35 | 36 | group :development, :test do 37 | gem 'rspec-rails', '~> 3.0' 38 | gem 'byebug' 39 | # Access an IRB console on exception pages or by using <%= console %> in views 40 | gem 'web-console', '~> 2.0' 41 | # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring 42 | gem 'spring' 43 | end 44 | 45 | group :test do 46 | gem 'database_cleaner' 47 | end -------------------------------------------------------------------------------- /app/views/req_purchases/edit.html.erb: -------------------------------------------------------------------------------- 1 | <%= req_edit_header("Редактировать заявку на закупку", "req_purchases", "Заявки на закупку", "Заявка на закупку") %> 2 |
3 |
4 |
5 |
6 |
7 |
Редактирование заявки на закупку
8 | 16 |
17 |
18 | <%= render 'shared/actions_and_assignees' %> 19 |
20 | <%= simple_form_for(@req) do |f| %> 21 | <%= f.input :id, disabled: true %> 22 | <%= f.input :state, disabled: true %> 23 | <%= f.input :name, disabled: @req.is_disabled?("name") %> 24 | <%= f.input :money, disabled: @req.is_disabled?("money") %> 25 | <%= render 'edit_myfile', f: f %> 26 | <%= render 'shared/req_edit_buttons', f: f %> 27 | <% end %> 28 |
29 |
30 |
31 |
32 |
33 | -------------------------------------------------------------------------------- /app/assets/stylesheets/base/badgets_labels.scss: -------------------------------------------------------------------------------- 1 | .label { 2 | background-color: $light-gray; 3 | color: $label-badget-color; 4 | font-family: "Open Sans"; 5 | font-size: 10px; 6 | font-weight: 600; 7 | padding: 3px 8px; 8 | text-shadow: none; 9 | } 10 | 11 | .badge { 12 | background-color: $light-gray; 13 | color: $label-badget-color; 14 | font-family: "Open Sans"; 15 | font-size: 11px; 16 | font-weight: 600; 17 | padding-bottom: 4px; 18 | padding-left: 6px; 19 | padding-right: 6px; 20 | text-shadow: none; 21 | } 22 | 23 | .label-primary, .badge-primary { 24 | background-color: $navy; 25 | color: white; 26 | } 27 | 28 | .label-success, .badge-success { 29 | background-color: $blue; 30 | color: white; 31 | } 32 | 33 | .label-warning, .badge-warning { 34 | background-color: $yellow; 35 | color: white; 36 | } 37 | 38 | .label-warning-light, .badge-warning-light { 39 | background-color: $yellow; 40 | color: white; 41 | } 42 | 43 | .label-danger, .badge-danger { 44 | background-color: $red; 45 | color: white; 46 | } 47 | 48 | .label-info, .badge-info { 49 | background-color: $lazur; 50 | color: white; 51 | } 52 | 53 | .label-inverse, .badge-inverse { 54 | background-color: #262626; 55 | color: white; 56 | } 57 | 58 | .label-white, .badge-white { 59 | background-color: white; 60 | color: #5e5e5e; 61 | } 62 | 63 | .label-white, .badge-disable { 64 | background-color: #2a2e36; 65 | color: #8b91a0; 66 | } 67 | -------------------------------------------------------------------------------- /db/migrate/20150515202844_devise_create_users.rb: -------------------------------------------------------------------------------- 1 | class DeviseCreateUsers < ActiveRecord::Migration 2 | def change 3 | create_table(:users) do |t| 4 | ## Database authenticatable 5 | t.string :email, null: false, default: "" 6 | t.string :encrypted_password, null: false, default: "" 7 | 8 | ## Recoverable 9 | t.string :reset_password_token 10 | t.datetime :reset_password_sent_at 11 | 12 | ## Rememberable 13 | t.datetime :remember_created_at 14 | 15 | ## Trackable 16 | t.integer :sign_in_count, default: 0, null: false 17 | t.datetime :current_sign_in_at 18 | t.datetime :last_sign_in_at 19 | t.inet :current_sign_in_ip 20 | t.inet :last_sign_in_ip 21 | 22 | ## Confirmable 23 | # t.string :confirmation_token 24 | # t.datetime :confirmed_at 25 | # t.datetime :confirmation_sent_at 26 | # t.string :unconfirmed_email # Only if using reconfirmable 27 | 28 | ## Lockable 29 | # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts 30 | # t.string :unlock_token # Only if unlock strategy is :email or :both 31 | # t.datetime :locked_at 32 | 33 | 34 | t.timestamps 35 | end 36 | 37 | add_index :users, :email, unique: true 38 | add_index :users, :reset_password_token, unique: true 39 | # add_index :users, :confirmation_token, unique: true 40 | # add_index :users, :unlock_token, unique: true 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /config/application.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../boot', __FILE__) 2 | 3 | require "rails" 4 | # Pick the frameworks you want: 5 | require "active_model/railtie" 6 | require "active_job/railtie" 7 | require "active_record/railtie" 8 | require "action_controller/railtie" 9 | require "action_mailer/railtie" 10 | require "action_view/railtie" 11 | require "sprockets/railtie" 12 | # require "rails/test_unit/railtie" 13 | 14 | # Require the gems listed in Gemfile, including any gems 15 | # you've limited to :test, :development, or :production. 16 | Bundler.require(*Rails.groups) 17 | 18 | module Bpm 19 | class Application < Rails::Application 20 | config.autoload_paths += %W(#{config.root}/lib) 21 | # Settings in config/environments/* take precedence over those specified here. 22 | # Application configuration should go into files in config/initializers 23 | # -- all .rb files in that directory are automatically loaded. 24 | 25 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. 26 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. 27 | # config.time_zone = 'Central Time (US & Canada)' 28 | 29 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. 30 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] 31 | # config.i18n.default_locale = :de 32 | 33 | # Do not swallow errors in after_commit/after_rollback callbacks. 34 | config.active_record.raise_in_transactional_callbacks = true 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /app/views/req_reassigns/new.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Создать заявку на перезакрепление

4 | 9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
Создание заявки на перезакрепление
17 |
18 | 19 | 20 |
21 |
22 |
23 | <%= simple_form_for(@req) do |f| %> 24 | <%= f.input :name %> 25 | <%= f.input :client_id, collection: Client.order(:name).where("manager_id = ?", current_user.id), label_method: :name, value_method: :id %> 26 | <%= f.input :new_manager_id, collection: User.order(:name).all, label_method: :name, value_method: :id %> 27 | <%= f.input :money %> 28 | <%= f.input :info %> 29 |
30 | <%= link_to "Отмена", @req, class: "btn btn-white"%> 31 | <%= f.submit :save, class: "btn btn-primary"%> 32 |
33 | <% end %> 34 |
35 |
36 |
37 |
38 |
39 | -------------------------------------------------------------------------------- /app/views/req_rolepurchases/edit.html.erb: -------------------------------------------------------------------------------- 1 | <%= req_edit_header("Редактировать заявку на закупку с ролями", "req_rolepurchases", "Заявки на закупку", "Заявка на закупку") %> 2 |
3 |
4 |
5 |
6 |
7 |
Редактирование заявки на закупку
8 | 16 |
17 |
18 | <%= render 'shared/actions_and_assignees' %> 19 |
20 | <%= simple_form_for(@req) do |f| %> 21 | <%= f.input :id, disabled: true %> 22 | <%= f.input :state, disabled: true %> 23 | <%= f.input :assign_user_id, collection: @req.users_list, label_method: :name, value_method: :id, :label => "Выберите клиентского менеджера", required: true %> 24 | <%= f.input :name, disabled: @req.is_disabled?("name") %> 25 | <%= f.input :money, disabled: @req.is_disabled?("money") %> 26 | <%= render 'shared/req_edit_buttons', f: f %> 27 | <% end %> 28 |
29 |
30 |
31 |
32 |
33 | -------------------------------------------------------------------------------- /app/assets/stylesheets/base/metismenu.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * metismenu - v2.0.2 3 | * A jQuery menu plugin 4 | * https://github.com/onokumus/metisMenu 5 | * 6 | * Made by Osman Nuri Okumus 7 | * Under MIT License 8 | */ 9 | 10 | .metismenu .plus-minus, .metismenu .plus-times { 11 | float: right 12 | } 13 | 14 | .metismenu .arrow { 15 | float: right; 16 | line-height: 1.42857 17 | } 18 | 19 | .metismenu .glyphicon.arrow:before { 20 | content: "\e079" 21 | } 22 | 23 | .metismenu .active > a > .glyphicon.arrow:before { 24 | content: "\e114" 25 | } 26 | 27 | .metismenu .fa.arrow:before { 28 | content: "\f104" 29 | } 30 | 31 | .metismenu .active > a > .fa.arrow:before { 32 | content: "\f107" 33 | } 34 | 35 | .metismenu .ion.arrow:before { 36 | content: "\f3d2" 37 | } 38 | 39 | .metismenu .active > a > .ion.arrow:before { 40 | content: "\f3d0" 41 | } 42 | 43 | .metismenu .fa.plus-minus:before, .metismenu .fa.plus-times:before { 44 | content: "\f067" 45 | } 46 | 47 | .metismenu .active > a > .fa.plus-times { 48 | -webkit-transform: rotate(45deg); 49 | -ms-transform: rotate(45deg); 50 | transform: rotate(45deg) 51 | } 52 | 53 | .metismenu .active > a > .fa.plus-minus:before { 54 | content: "\f068" 55 | } 56 | 57 | .metismenu .collapse { 58 | display: none 59 | } 60 | 61 | .metismenu .collapse.in { 62 | display: block 63 | } 64 | 65 | .metismenu .collapsing { 66 | position: relative; 67 | height: 0; 68 | overflow: hidden; 69 | -webkit-transition-timing-function: ease; 70 | transition-timing-function: ease; 71 | -webkit-transition-duration: .35s; 72 | transition-duration: .35s; 73 | -webkit-transition-property: height, visibility; 74 | transition-property: height, visibility 75 | } 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | We're sorry, but something went wrong (500) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

We're sorry, but something went wrong.

62 |
63 |

If you are the application owner check the logs for more information.

64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The change you wanted was rejected (422) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The change you wanted was rejected.

62 |

Maybe you tried to change something you didn't have access to.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The page you were looking for doesn't exist (404) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The page you were looking for doesn't exist.

62 |

You may have mistyped the address or the page may have moved.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /app/models/req_workgroup.rb: -------------------------------------------------------------------------------- 1 | class ReqWorkgroup < ActiveRecord::Base 2 | include ReqMain 3 | after_initialize :init 4 | after_create :set_assignee 5 | has_many :assignments, as: :assignable 6 | validates :name, presence: true 7 | belongs_to :last_user, class_name: "User" 8 | has_many :history, as: :historyable 9 | 10 | has_many :inf_workgroup_members, dependent: :destroy 11 | accepts_nested_attributes_for :inf_workgroup_members, allow_destroy: true, 12 | reject_if: proc { |attributes| attributes['user_id'].blank? } 13 | 14 | # validate :one_group_leader 15 | 16 | state_machine :initial => :new do 17 | # before_transition :new => :active, :do => :create_assignment 18 | before_transition :active => :closed, :do => :close_myassignment 19 | after_transition any => any, :do => :write_history 20 | 21 | event :initiate do 22 | transition :new => :active 23 | end 24 | 25 | event :close do 26 | transition :active => :closed 27 | end 28 | 29 | end 30 | 31 | private 32 | 33 | def init 34 | self.state ||= 'new' 35 | @disabled = Hash.new{|hash, key| hash[key] = Hash.new} 36 | @disabled["new"]["name"] = false 37 | @disabled["new"]["money"] = false 38 | @disabled["new"]["description"] = false 39 | @disabled["active"]["name"] = false 40 | @disabled["active"]["money"] = false 41 | @disabled["active"]["description"] = false 42 | end 43 | 44 | def close_myassignment 45 | Rails.logger.info('!!!!! close_assignment') 46 | close_assignment(self.last_user_id) 47 | end 48 | 49 | #validations 50 | 51 | # def one_group_leader 52 | # Rails.logger.info('!!!!! one_group_leader') 53 | # Rails.logger.info(self.inf_workgroup_members.where(main: true).count) 54 | # if self.inf_workgroup_members.where(main: true).count > 1 55 | # errors.add(:base, :validate_one_leader) 56 | # end 57 | # end 58 | 59 | end 60 | -------------------------------------------------------------------------------- /app/controllers/req_workgroups_controller.rb: -------------------------------------------------------------------------------- 1 | class ReqWorkgroupsController < ApplicationController 2 | # before_action :authenticate_user! 3 | before_filter :not_assigned, only: [:edit, :update] 4 | 5 | def index 6 | @reqs = ReqWorkgroup.all.order('id desc') #where('state not in (?)', 'closed').order('id desc') 7 | end 8 | 9 | def new 10 | @req = ReqWorkgroup.new 11 | end 12 | 13 | def create 14 | @req = ReqWorkgroup.new(req_params) 15 | @req.set_last_user(current_user) 16 | if @req.save 17 | redirect_to @req 18 | else 19 | render 'new' 20 | end 21 | end 22 | 23 | def show 24 | @req = ReqWorkgroup.find(params[:id]) 25 | @history = @req.history 26 | end 27 | 28 | def edit 29 | @req=ReqWorkgroup.find(params[:id]) 30 | end 31 | 32 | def update 33 | @req = ReqWorkgroup.find(params[:id]) 34 | @req.set_last_user(current_user) 35 | leader_count = params["req_workgroup"]["inf_workgroup_members_attributes"].select.count {|k,v| v["main"]=="1" && v["_destroy"]=="false"} 36 | Rails.logger.info('!!!!! leader_count '+ leader_count.to_s) 37 | @req.assign_attributes(req_params) 38 | if (leader_count > 1) 39 | flash.now[:warning] = t(:should_be_only_one_leader) 40 | render 'edit' 41 | else 42 | action = params[:commit] 43 | if @req.send(action) 44 | flash[:success] = t(:req_updated_successfuly) 45 | redirect_to @req 46 | else 47 | render 'edit' 48 | end 49 | end 50 | end 51 | 52 | private 53 | 54 | def req_params 55 | params.require(:req_workgroup).permit(:name, :money, :description, 56 | inf_workgroup_members_attributes: [:id, :user_id, :main, :comment, :_destroy]) 57 | end 58 | 59 | def not_assigned 60 | req = ReqWorkgroup.find(params[:id]) 61 | unless req.is_assigned?(current_user) 62 | redirect_to root_path 63 | end 64 | end 65 | 66 | end 67 | -------------------------------------------------------------------------------- /app/uploaders/myfile_uploader.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | CarrierWave::SanitizedFile.sanitize_regexp = /[^a-zA-Zа-яА-ЯёЁ0-9\.\_\-\+\s\:]/ 3 | 4 | class MyfileUploader < CarrierWave::Uploader::Base 5 | 6 | # Include RMagick or MiniMagick support: 7 | # include CarrierWave::RMagick 8 | # include CarrierWave::MiniMagick 9 | 10 | # Choose what kind of storage to use for this uploader: 11 | storage :file 12 | # storage :fog 13 | 14 | def extension_white_list 15 | %w(doc docx pdf) 16 | end 17 | 18 | # Override the directory where uploaded files will be stored. 19 | # This is a sensible default for uploaders that are meant to be mounted: 20 | def store_dir 21 | "system/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" 22 | end 23 | 24 | def cache_dir 25 | 'system/uploads/tmp' 26 | end 27 | 28 | # Provide a default URL as a default if there hasn't been a file uploaded: 29 | # def default_url 30 | # # For Rails 3.1+ asset pipeline compatibility: 31 | # # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_')) 32 | # 33 | # "/images/fallback/" + [version_name, "default.png"].compact.join('_') 34 | # end 35 | 36 | # Process files as they are uploaded: 37 | # process :scale => [200, 300] 38 | # 39 | # def scale(width, height) 40 | # # do something 41 | # end 42 | 43 | # Create different versions of your uploaded files: 44 | # version :thumb do 45 | # process :resize_to_fit => [50, 50] 46 | # end 47 | 48 | # Add a white list of extensions which are allowed to be uploaded. 49 | # For images you might use something like this: 50 | # def extension_white_list 51 | # %w(jpg jpeg gif png) 52 | # end 53 | 54 | # Override the filename of the uploaded files: 55 | # Avoid using model.id or version_name here, see uploader/store.rb for details. 56 | # def filename 57 | # "something.jpg" if original_filename 58 | # end 59 | 60 | end 61 | -------------------------------------------------------------------------------- /config/environments/development.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # In the development environment your application's code is reloaded on 5 | # every request. This slows down response time but is perfect for development 6 | # since you don't have to restart the web server when you make code changes. 7 | config.action_mailer.default_url_options = { :host => 'localhost:3000' } 8 | 9 | config.i18n.default_locale = :ru 10 | config.i18n.available_locales = :ru 11 | 12 | config.cache_classes = false 13 | 14 | # Do not eager load code on boot. 15 | config.eager_load = false 16 | 17 | # Show full error reports and disable caching. 18 | config.consider_all_requests_local = true 19 | config.action_controller.perform_caching = false 20 | 21 | # Don't care if the mailer can't send. 22 | config.action_mailer.raise_delivery_errors = false 23 | 24 | # Print deprecation notices to the Rails logger. 25 | config.active_support.deprecation = :log 26 | 27 | # Raise an error on page load if there are pending migrations. 28 | config.active_record.migration_error = :page_load 29 | 30 | # Debug mode disables concatenation and preprocessing of assets. 31 | # This option may cause significant delays in view rendering with a large 32 | # number of complex assets. 33 | config.assets.debug = true 34 | 35 | # Asset digests allow you to set far-future HTTP expiration dates on all assets, 36 | # yet still be able to expire them through the digest params. 37 | config.assets.digest = true 38 | 39 | # Adds additional error checking when serving assets at runtime. 40 | # Checks for improperly declared sprockets dependencies. 41 | # Raises helpful error messages. 42 | config.assets.raise_runtime_errors = true 43 | 44 | # Raises error for missing translations 45 | # config.action_view.raise_on_missing_translations = true 46 | config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } 47 | end 48 | -------------------------------------------------------------------------------- /app/views/req_reassigns/edit.html.erb: -------------------------------------------------------------------------------- 1 | <%= req_edit_header("Редактировать заявку на перезакрепление", "req_reassigns", "Заявки на перезакрепление", "Заявка") %> 2 |
3 |
4 |
5 |
6 |
7 |
Редактирование заявки на перезакрепление
8 | 16 |
17 |
18 | <%= render 'shared/actions_and_assignees' %> 19 |
20 | <%= simple_form_for(@req) do |f| %> 21 | <%= f.input :id, disabled: true %> 22 | <%= f.input :state, disabled: true %> 23 | <%= f.input :name, disabled: @req.is_disabled?("name") %> 24 | <%= f.input :client_id, collection: Client.order(:name).all, label_method: :name, value_method: :id, disabled: @req.is_disabled?("client")%> 25 | <%= f.input :old_manager_id, collection: User.order(:name).all, label_method: :name, value_method: :id, disabled: true %> 26 | <%= f.input :new_manager_id, collection: User.order(:name).all, label_method: :name, value_method: :id, disabled: @req.is_disabled?("new_manager") %> 27 | <%= f.input :money, disabled: @req.is_disabled?("money") %> 28 | <%= f.input :info, disabled: @req.is_disabled?("info") %> 29 | <%= render 'shared/req_edit_buttons', f: f %> 30 | <% end %> 31 |
32 |
33 |
34 |
35 |
36 | -------------------------------------------------------------------------------- /config/environments/test.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # The test environment is used exclusively to run your application's 5 | # test suite. You never need to work with it otherwise. Remember that 6 | # your test database is "scratch space" for the test suite and is wiped 7 | # and recreated between test runs. Don't rely on the data there! 8 | # Rails.application.routes.default_url_options[:host] = 'localhost:3000' 9 | config.action_mailer.default_url_options = { :host => 'localhost:3000' } 10 | 11 | config.cache_classes = true 12 | 13 | # Do not eager load code on boot. This avoids loading your whole application 14 | # just for the purpose of running a single test. If you are using a tool that 15 | # preloads Rails for running tests, you may have to set it to true. 16 | config.eager_load = false 17 | 18 | # Configure static file server for tests with Cache-Control for performance. 19 | config.serve_static_files = true 20 | config.static_cache_control = 'public, max-age=3600' 21 | 22 | # Show full error reports and disable caching. 23 | config.consider_all_requests_local = true 24 | config.action_controller.perform_caching = false 25 | 26 | # Raise exceptions instead of rendering exception templates. 27 | config.action_dispatch.show_exceptions = false 28 | 29 | # Disable request forgery protection in test environment. 30 | config.action_controller.allow_forgery_protection = false 31 | 32 | # Tell Action Mailer not to deliver emails to the real world. 33 | # The :test delivery method accumulates sent emails in the 34 | # ActionMailer::Base.deliveries array. 35 | config.action_mailer.delivery_method = :test 36 | 37 | # Randomize the order test cases are executed. 38 | config.active_support.test_order = :random 39 | 40 | # Print deprecation notices to the stderr. 41 | config.active_support.deprecation = :stderr 42 | 43 | # Raises error for missing translations 44 | # config.action_view.raise_on_missing_translations = true 45 | end 46 | -------------------------------------------------------------------------------- /config/deploy/shared/unicorn_init.sh.erb: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### BEGIN INIT INFO 3 | # Provides: unicorn 4 | # Required-Start: $remote_fs $syslog 5 | # Required-Stop: $remote_fs $syslog 6 | # Default-Start: 2 3 4 5 7 | # Default-Stop: 0 1 6 8 | # Short-Description: Manage unicorn server 9 | # Description: Start, stop, restart unicorn server for a specific application. 10 | ### END INIT INFO 11 | set -e 12 | 13 | # Feel free to change any of the following variables for your app: 14 | TIMEOUT=${TIMEOUT-60} 15 | APP_ROOT=/home/mike/apps/testcap_production/current 16 | PID=$APP_ROOT/tmp/pids/unicorn.pid 17 | CMD="cd $APP_ROOT; bundle exec unicorn -D -c $APP_ROOT/config/unicorn.rb -E production" 18 | AS_USER=mike 19 | set -u 20 | 21 | OLD_PIN="$PID.oldbin" 22 | 23 | sig () { 24 | test -s "$PID" && kill -$1 `cat $PID` 25 | } 26 | 27 | oldsig () { 28 | test -s $OLD_PIN && kill -$1 `cat $OLD_PIN` 29 | } 30 | 31 | run () { 32 | if [ "$(id -un)" = "$AS_USER" ]; then 33 | eval $1 34 | else 35 | su -c "$1" - $AS_USER 36 | fi 37 | } 38 | 39 | case "$1" in 40 | start) 41 | sig 0 && echo >&2 "Already running" && exit 0 42 | run "$CMD" 43 | ;; 44 | stop) 45 | sig QUIT && exit 0 46 | echo >&2 "Not running" 47 | ;; 48 | force-stop) 49 | sig TERM && exit 0 50 | echo >&2 "Not running" 51 | ;; 52 | restart|reload) 53 | sig HUP && echo reloaded OK && exit 0 54 | echo >&2 "Couldn't reload, starting '$CMD' instead" 55 | run "$CMD" 56 | ;; 57 | upgrade) 58 | if sig USR2 && sleep 2 && sig 0 && oldsig QUIT 59 | then 60 | n=$TIMEOUT 61 | while test -s $OLD_PIN && test $n -ge 0 62 | do 63 | printf '.' && sleep 1 && n=$(( $n - 1 )) 64 | done 65 | echo 66 | 67 | if test $n -lt 0 && test -s $OLD_PIN 68 | then 69 | echo >&2 "$OLD_PIN still exists after $TIMEOUT seconds" 70 | exit 1 71 | fi 72 | exit 0 73 | fi 74 | echo >&2 "Couldn't upgrade, starting '$CMD' instead" 75 | run "$CMD" 76 | ;; 77 | reopen-logs) 78 | sig USR1 79 | ;; 80 | *) 81 | echo >&2 "Usage: $0 " 82 | exit 1 83 | ;; 84 | esac -------------------------------------------------------------------------------- /app/controllers/req_reassigns_controller.rb: -------------------------------------------------------------------------------- 1 | class ReqReassignsController < ApplicationController 2 | # before_action :authenticate_user! 3 | before_filter :not_assigned, only: [:edit, :update] 4 | 5 | def index 6 | @reqs = ReqReassign.where('state not in (?)', 'closed').order('id desc') 7 | end 8 | 9 | def new 10 | @req = ReqReassign.new 11 | # @req.old_manager_id = current_user.id 12 | end 13 | 14 | def create 15 | params[:req_reassign][:last_user_id] = current_user.id 16 | params[:req_reassign][:old_manager_id] = current_user.id 17 | 18 | @req = ReqReassign.new(req_params) 19 | if @req.save 20 | redirect_to @req 21 | else 22 | render 'new' 23 | end 24 | end 25 | 26 | def show 27 | @req = ReqReassign.find(params[:id]) 28 | @history = @req.history 29 | respond_to do |format| 30 | format.html 31 | end 32 | end 33 | 34 | def edit 35 | @req=ReqReassign.find(params[:id]) 36 | end 37 | 38 | def update 39 | # params[:req_reassign][:last_user_id] = current_user.id 40 | @req = ReqReassign.find(params[:id]) 41 | @req.set_last_user(current_user) 42 | action = params[:commit] 43 | Rails.logger.info('!!!!!'+action) if action 44 | if action == 'save' 45 | # @req = ReqReassign.find(params[:id]) 46 | if @req.update_attributes(req_params) 47 | flash[:success] = t(:req_updated_successfuly) 48 | redirect_to @req 49 | else 50 | render 'edit' 51 | end 52 | else 53 | # @req = ReqReassign.find(params[:id]) 54 | @req.assign_attributes(req_params) 55 | if @req.send(action) 56 | flash[:success] = t(:req_updated_successfuly) 57 | redirect_to @req 58 | else 59 | render 'edit' 60 | end 61 | end 62 | end 63 | 64 | private 65 | 66 | def req_params 67 | params.require(:req_reassign).permit(:old_manager_id, :money, :new_manager_id, :info, :client_id, :last_user_id, :name) 68 | end 69 | 70 | def not_assigned 71 | req = ReqReassign.find(params[:id]) 72 | unless req.is_assigned?(current_user) 73 | redirect_to root_path 74 | end 75 | end 76 | 77 | end 78 | -------------------------------------------------------------------------------- /spec/features/user_login_and_logout_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | feature "User logs in and logs out" do 4 | 5 | # `js: true` spec metadata means this will run using the `:selenium` 6 | # browser driver configured in spec/support/capybara.rb 7 | scenario "with correct details" do 8 | 9 | create(:user, email: "manager1@test.com", name: "Mike Klishevich", 10 | password: "testtest") 11 | 12 | visit "/" 13 | 14 | expect(page).to have_css("h2", text: "Вход") 15 | expect(current_path).to eq(new_user_session_path) 16 | 17 | login "manager1@test.com", "testtest" 18 | 19 | # expect(page).to have_selector('a.font-bold', text: 'Mike') 20 | 21 | expect(page).to have_content "Mike Klishevich" 22 | 23 | expect(page).to have_content "Главная" 24 | 25 | click_link "log_out" 26 | 27 | expect(page).to have_css("h2", text: "Вход") 28 | 29 | end 30 | 31 | # scenario "unconfirmed user cannot login" do 32 | 33 | # create(:user, skip_confirmation: false, email: "e@example.tld", password: "test-password") 34 | 35 | # visit new_user_session_path 36 | 37 | # login "e@example.tld", "test-password" 38 | 39 | # expect(current_path).to eq(new_user_session_path) 40 | # expect(page).not_to have_content "Signed in successfully" 41 | # expect(page).to have_content "You have to confirm your email address before continuing" 42 | # end 43 | 44 | # scenario "locks account after 3 failed attempts" do 45 | 46 | # email = "someone@example.tld" 47 | # create(:user, email: email, password: "somepassword") 48 | 49 | # visit new_user_session_path 50 | 51 | # login email, "1st-try-wrong-password" 52 | # expect(page).to have_content "Invalid email or password" 53 | 54 | # login email, "2nd-try-wrong-password" 55 | # expect(page).to have_content "You have one more attempt before your account is locked" 56 | 57 | # login email, "3rd-try-wrong-password" 58 | # expect(page).to have_content "Your account is locked." 59 | 60 | # end 61 | 62 | private 63 | 64 | def login(email, password) 65 | fill_in "user_email", with: email 66 | fill_in "user_password", with: password 67 | click_button "log_in" 68 | end 69 | 70 | end -------------------------------------------------------------------------------- /config/deploy/staging.rb: -------------------------------------------------------------------------------- 1 | # server-based syntax 2 | # ====================== 3 | # Defines a single server with a list of roles and multiple properties. 4 | # You can define all roles on a single server, or split them: 5 | 6 | # server 'example.com', user: 'deploy', roles: %w{app db web}, my_property: :my_value 7 | # server 'example.com', user: 'deploy', roles: %w{app web}, other_property: :other_value 8 | # server 'db.example.com', user: 'deploy', roles: %w{db} 9 | 10 | 11 | 12 | # role-based syntax 13 | # ================== 14 | 15 | # Defines a role with one or multiple servers. The primary server in each 16 | # group is considered to be the first unless any hosts have the primary 17 | # property set. Specify the username and a domain or IP for the server. 18 | # Don't use `:all`, it's a meta role. 19 | 20 | # role :app, %w{deploy@example.com}, my_property: :my_value 21 | # role :web, %w{user1@primary.com user2@additional.com}, other_property: :other_value 22 | # role :db, %w{deploy@example.com} 23 | 24 | 25 | 26 | # Configuration 27 | # ============= 28 | # You can set any configuration variable like in config/deploy.rb 29 | # These variables are then only loaded and set in this stage. 30 | # For available Capistrano configuration variables see the documentation page. 31 | # http://capistranorb.com/documentation/getting-started/configuration/ 32 | # Feel free to add new variables to customise your setup. 33 | 34 | 35 | 36 | # Custom SSH Options 37 | # ================== 38 | # You may pass any option but keep in mind that net/ssh understands a 39 | # limited set of options, consult the Net::SSH documentation. 40 | # http://net-ssh.github.io/net-ssh/classes/Net/SSH.html#method-c-start 41 | # 42 | # Global options 43 | # -------------- 44 | # set :ssh_options, { 45 | # keys: %w(/home/rlisowski/.ssh/id_rsa), 46 | # forward_agent: false, 47 | # auth_methods: %w(password) 48 | # } 49 | # 50 | # The server-based syntax can be used to override options: 51 | # ------------------------------------ 52 | # server 'example.com', 53 | # user: 'user_name', 54 | # roles: %w{web app}, 55 | # ssh_options: { 56 | # user: 'user_name', # overrides user setting above 57 | # keys: %w(/home/user_name/.ssh/id_rsa), 58 | # forward_agent: false, 59 | # auth_methods: %w(publickey password) 60 | # # password: 'please use keys' 61 | # } 62 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | get 'assignments' => 'assignments#index' 3 | 4 | get 'reports' => 'reports#index' 5 | get 'reports/sla' => 'reports#sla' 6 | post 'reports/sla' => 'reports#sla' 7 | 8 | devise_for :users 9 | resources :users 10 | # get 'req_reassigns/index' 11 | 12 | # get 'req_reassigns/new' 13 | 14 | # get 'req_reassigns/create' 15 | 16 | # get 'req_reassigns/show' 17 | resources :req_rolepurchases 18 | 19 | resources :req_workgroups 20 | 21 | resources :req_purchases 22 | 23 | resources :req_reassigns 24 | 25 | # The priority is based upon order of creation: first created -> highest priority. 26 | # See how all your routes lay out with "rake routes". 27 | 28 | # You can have the root of your site routed with "root" 29 | root 'static_pages#home' 30 | 31 | # Example of regular route: 32 | # get 'products/:id' => 'catalog#view' 33 | 34 | # Example of named route that can be invoked with purchase_url(id: product.id) 35 | # get 'products/:id/purchase' => 'catalog#purchase', as: :purchase 36 | 37 | # Example resource route (maps HTTP verbs to controller actions automatically): 38 | # resources :products 39 | 40 | # Example resource route with options: 41 | # resources :products do 42 | # member do 43 | # get 'short' 44 | # post 'toggle' 45 | # end 46 | # 47 | # collection do 48 | # get 'sold' 49 | # end 50 | # end 51 | 52 | # Example resource route with sub-resources: 53 | # resources :products do 54 | # resources :comments, :sales 55 | # resource :seller 56 | # end 57 | 58 | # Example resource route with more complex sub-resources: 59 | # resources :products do 60 | # resources :comments 61 | # resources :sales do 62 | # get 'recent', on: :collection 63 | # end 64 | # end 65 | 66 | # Example resource route with concerns: 67 | # concern :toggleable do 68 | # post 'toggle' 69 | # end 70 | # resources :posts, concerns: :toggleable 71 | # resources :photos, concerns: :toggleable 72 | 73 | # Example resource route within a namespace: 74 | # namespace :admin do 75 | # # Directs /admin/products/* to Admin::ProductsController 76 | # # (app/controllers/admin/products_controller.rb) 77 | # resources :products 78 | # end 79 | end 80 | -------------------------------------------------------------------------------- /app/assets/stylesheets/base/theme-config.scss: -------------------------------------------------------------------------------- 1 | /* 2 | * This is style for skin config 3 | * Use only in demo theme 4 | */ 5 | 6 | .theme-config { 7 | position: absolute; 8 | top: 90px; 9 | right: 0px; 10 | overflow: hidden; 11 | } 12 | 13 | .theme-config-box { 14 | margin-right: -220px; 15 | position: relative; 16 | z-index: 2000; 17 | transition-duration: 0.8s; 18 | } 19 | 20 | .theme-config-box.show { 21 | margin-right: 0px; 22 | } 23 | 24 | .spin-icon { 25 | background: $navy; 26 | position: absolute; 27 | padding: 7px 10px 7px 13px; 28 | border-radius: 20px 0px 0px 20px; 29 | font-size: 16px; 30 | top: 0; 31 | left: 0px; 32 | width: 40px; 33 | color: white; 34 | cursor: pointer; 35 | } 36 | 37 | .skin-setttings { 38 | width: 220px; 39 | margin-left: 40px; 40 | background: $gray; 41 | } 42 | 43 | .skin-setttings .title { 44 | background: #efefef; 45 | text-align: center; 46 | text-transform: uppercase; 47 | font-weight: 600; 48 | display: block; 49 | padding: 10px 15px; 50 | font-size: 12px; 51 | } 52 | 53 | .setings-item { 54 | padding: 10px 30px; 55 | } 56 | 57 | .setings-item.skin { 58 | text-align: center; 59 | } 60 | 61 | .setings-item .switch { 62 | float: right; 63 | } 64 | 65 | .skin-name a { 66 | text-transform: uppercase; 67 | } 68 | 69 | .setings-item a { 70 | color: white; 71 | } 72 | 73 | .default-skin, .blue-skin, .ultra-skin, .yellow-skin { 74 | text-align: center; 75 | } 76 | 77 | .default-skin { 78 | font-weight: 600; 79 | background: #1ab394; 80 | } 81 | 82 | .default-skin:hover { 83 | background: #199d82; 84 | } 85 | 86 | .blue-skin { 87 | font-weight: 600; 88 | background: url("patterns/header-profile-skin-1.png") repeat scroll 0 0; 89 | } 90 | 91 | .blue-skin:hover { 92 | background: #0d8ddb; 93 | } 94 | 95 | .yellow-skin { 96 | font-weight: 600; 97 | background: url("patterns/header-profile-skin-3.png") repeat scroll 0 100%; 98 | } 99 | 100 | .yellow-skin:hover { 101 | background: #ce8735; 102 | } 103 | 104 | .ultra-skin { 105 | font-weight: 600; 106 | background: url("patterns/header-profile-skin-2.png") repeat scroll 0 0; 107 | } 108 | 109 | .ultra-skin:hover { 110 | background: #1a2d40; 111 | } 112 | -------------------------------------------------------------------------------- /app/controllers/req_rolepurchases_controller.rb: -------------------------------------------------------------------------------- 1 | class ReqRolepurchasesController < ApplicationController 2 | before_filter :not_assigned, only: [:edit, :update] 3 | 4 | def index 5 | @reqs = ReqRolepurchase.where('state not in (?)', 'closed').order('id desc') 6 | end 7 | 8 | def new 9 | @req = ReqRolepurchase.new 10 | end 11 | 12 | def create 13 | Rails.logger.info('!!!!! create') 14 | Rails.logger.info(params) 15 | # params[:req_purchase][:last_user_id] = current_user.id 16 | @req = ReqRolepurchase.new(req_params) 17 | @req.set_last_user(current_user) 18 | if @req.save 19 | redirect_to @req 20 | else 21 | render 'new' 22 | end 23 | end 24 | 25 | def show 26 | @req = ReqRolepurchase.find(params[:id]) 27 | @history = @req.history 28 | respond_to do |format| 29 | format.html 30 | end 31 | end 32 | 33 | def edit 34 | @req=ReqRolepurchase.find(params[:id]) 35 | end 36 | 37 | def update 38 | # params['req_purchase'] = Hash.new 39 | # Rails.logger.info('!!!!! update') 40 | # Rails.logger.info(params) 41 | # params[:req_purchase][:last_user_id] = current_user.id 42 | @req = ReqRolepurchase.find(params[:id]) 43 | @req.set_last_user(current_user) 44 | action = params[:commit] 45 | Rails.logger.info('!!!!!'+action) if action 46 | # Rails.logger.info(params.inspect) 47 | params.inspect 48 | if action == 'save' 49 | # @req = ReqRolepurchase.find(params[:id]) 50 | if @req.update_attributes(req_params) 51 | flash[:success] = t(:req_updated_successfuly) 52 | redirect_to @req 53 | else 54 | render 'edit' 55 | end 56 | else 57 | # @req = ReqRolepurchase.find(params[:id]) 58 | @req.assign_attributes(req_params) 59 | if @req.send(action) 60 | flash[:success] = t(:req_updated_successfuly) 61 | redirect_to @req 62 | else 63 | render 'edit' 64 | end 65 | end 66 | end 67 | 68 | private 69 | 70 | def req_params 71 | params.fetch(:req_rolepurchase, Hash.new).permit(:name, :money, :last_user_id, :assign_user_id) 72 | # params.require(:req_purchase).permit(:name, :money, :last_user_id) 73 | end 74 | 75 | def not_assigned 76 | req = ReqRolepurchase.find(params[:id]) 77 | unless req.is_assigned?(current_user) 78 | redirect_to root_path 79 | end 80 | end 81 | end 82 | -------------------------------------------------------------------------------- /config/deploy.rb: -------------------------------------------------------------------------------- 1 | # config valid only for current version of Capistrano 2 | lock '3.4.0' 3 | 4 | set :application, 'bpm' 5 | set :deploy_user, 'mike' 6 | 7 | 8 | set :scm, :git 9 | set :repo_url, 'git@github.com:klishevich/bpm.git' 10 | set :assets_roles, [:app] 11 | set :keep_releases, 5 12 | set :linked_files, %w{config/database.yml config/secrets.yml} 13 | set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system} 14 | set :tests, [] 15 | set(:config_files, %w( 16 | database.yml 17 | unicorn_init.sh 18 | secrets.yml 19 | )) 20 | set(:executable_config_files, %w( 21 | unicorn_init.sh 22 | )) 23 | set(:symlinks, [ 24 | { 25 | # source: "/home/mike/apps/{{full_app_name}}/shared/config/unicorn_init.sh", 26 | # link: "/etc/init.d/unicorn_{{full_app_name}}" 27 | } 28 | ]) 29 | 30 | # Default branch is :master 31 | # ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp 32 | 33 | # Default deploy_to directory is /var/www/my_app_name 34 | # set :deploy_to, '/var/www/my_app_name' 35 | 36 | # Default value for :scm is :git 37 | # set :scm, :git 38 | 39 | # Default value for :format is :pretty 40 | # set :format, :pretty 41 | 42 | # Default value for :log_level is :debug 43 | # set :log_level, :debug 44 | 45 | # Default value for :pty is false 46 | # set :pty, true 47 | 48 | # Default value for :linked_files is [] 49 | # set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/secrets.yml') 50 | 51 | # Default value for linked_dirs is [] 52 | # set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system') 53 | 54 | # Default value for default_env is {} 55 | # set :default_env, { path: "/opt/ruby/bin:$PATH" } 56 | 57 | # Default value for keep_releases is 5 58 | # set :keep_releases, 5 59 | 60 | namespace :deploy do 61 | 62 | after :restart, :clear_cache do 63 | on roles(:web), in: :groups, limit: 3, wait: 10 do 64 | before :deploy, "deploy:check_revision" 65 | after :finishing, 'deploy:cleanup' 66 | after 'deploy:setup_config', 'nginx:reload' 67 | after 'deploy:publishing', 'deploy:restart' 68 | end 69 | end 70 | 71 | desc 'Restart application' 72 | task :restart do 73 | invoke 'unicorn:restart2' 74 | end 75 | 76 | end 77 | 78 | namespace :unicorn do 79 | 80 | desc 'Restart unicorn 2' 81 | task :restart2 do 82 | on roles(:app) do 83 | execute "/etc/init.d/unicorn_bpm_production restart" 84 | end 85 | end 86 | 87 | end 88 | -------------------------------------------------------------------------------- /app/controllers/req_purchases_controller.rb: -------------------------------------------------------------------------------- 1 | class ReqPurchasesController < ApplicationController 2 | # before_action :authenticate_user! 3 | before_filter :not_assigned, only: [:edit, :update] 4 | 5 | def index 6 | # @reqs = ReqPurchase.all.order('id desc') 7 | @reqs = ReqPurchase.where('state not in (?)', 'closed').order('id desc') 8 | end 9 | 10 | def new 11 | @req = ReqPurchase.new 12 | end 13 | 14 | def create 15 | Rails.logger.info('!!!!! create') 16 | Rails.logger.info(params) 17 | # params[:req_purchase][:last_user_id] = current_user.id 18 | @req = ReqPurchase.new(req_params) 19 | @req.set_last_user(current_user) 20 | if @req.save 21 | redirect_to @req 22 | else 23 | render 'new' 24 | end 25 | end 26 | 27 | def show 28 | @req = ReqPurchase.find(params[:id]) 29 | @history = @req.history 30 | respond_to do |format| 31 | format.html 32 | end 33 | end 34 | 35 | def edit 36 | @req=ReqPurchase.find(params[:id]) 37 | end 38 | 39 | def update 40 | # params['req_purchase'] = Hash.new 41 | # Rails.logger.info('!!!!! update') 42 | # Rails.logger.info(params) 43 | # params[:req_purchase][:last_user_id] = current_user.id 44 | @req = ReqPurchase.find(params[:id]) 45 | @req.set_last_user(current_user) 46 | action = params[:commit] 47 | Rails.logger.info('!!!!!'+action) if action 48 | # Rails.logger.info(params.inspect) 49 | params.inspect 50 | if action == 'save' 51 | # @req = ReqPurchase.find(params[:id]) 52 | if @req.update_attributes(req_params) 53 | flash[:success] = t(:req_updated_successfuly) 54 | redirect_to @req 55 | else 56 | render 'edit' 57 | end 58 | else 59 | # @req = ReqPurchase.find(params[:id]) 60 | @req.assign_attributes(req_params) 61 | if @req.send(action) 62 | flash[:success] = t(:req_updated_successfuly) 63 | redirect_to @req 64 | else 65 | render 'edit' 66 | end 67 | end 68 | end 69 | 70 | private 71 | 72 | def req_params 73 | params.fetch(:req_purchase, Hash.new).permit(:name, :money, :last_user_id, :myfile, 74 | :myfile_cache, :remove_myfile) 75 | # params.require(:req_purchase).permit(:name, :money, :last_user_id) 76 | end 77 | 78 | def not_assigned 79 | req = ReqPurchase.find(params[:id]) 80 | unless req.is_assigned?(current_user) 81 | redirect_to root_path 82 | end 83 | end 84 | end 85 | -------------------------------------------------------------------------------- /app/views/users/edit.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Редактировать пользователя

4 | 10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
Редактирование пользователя
18 | 26 |
27 |
28 | <%= simple_form_for(@user) do |f| %> 29 | <%= f.input :id, disabled: true %> 30 | <%= f.input :name %> 31 | <%= f.input :email, disabled: true %> 32 | <%= f.input :code %> 33 | <%= f.input :unit_id, collection: Unit.order(:name).all, label_method: :name, value_method: :id %> 34 | <%= f.input :deleted %> 35 | <%= f.input :admin %> 36 |
37 |

Роли

38 | <%= f.simple_fields_for :users_roles do |p| %> 39 | <%= render 'users_role_fields', f: p %> 40 | <% end %> 41 | 44 |
45 |
46 |
47 | <%= link_to "Отмена", users_path, class: "btn btn-white"%> 48 | <%= f.submit :save, class: "btn btn-primary"%> 49 |
50 | <% end %> 51 |
52 |
53 |
54 |
55 |
56 | -------------------------------------------------------------------------------- /app/assets/stylesheets/base/chat.scss: -------------------------------------------------------------------------------- 1 | #small-chat { 2 | position: fixed; 3 | bottom: 20px; 4 | right: 20px; 5 | z-index: 100; 6 | } 7 | 8 | #small-chat .badge { 9 | position: absolute; 10 | top: -3px; 11 | right: -4px; 12 | } 13 | 14 | .open-small-chat { 15 | height: 38px; 16 | width: 38px; 17 | display: block; 18 | background: #1ab394; 19 | padding: 9px 8px; 20 | text-align: center; 21 | color: #fff; 22 | border-radius: 50%; 23 | } 24 | 25 | .open-small-chat:hover { 26 | color: white; 27 | background: #1ab394; 28 | } 29 | 30 | 31 | .small-chat-box { 32 | display: none; 33 | position: fixed; 34 | bottom: 20px; 35 | right: 75px; 36 | background: #fff; 37 | border: 1px solid $border-color; 38 | width: 230px; 39 | height: 320px; 40 | border-radius: 4px; 41 | } 42 | 43 | .small-chat-box.ng-small-chat { 44 | display: block; 45 | } 46 | 47 | .body-small { 48 | .small-chat-box { 49 | bottom: 70px; 50 | right: 20px; 51 | } 52 | } 53 | 54 | .small-chat-box.active { 55 | display: block; 56 | } 57 | 58 | .small-chat-box { 59 | 60 | .heading { 61 | background: $nav-bg; 62 | padding: 8px 15px; 63 | font-weight: bold; 64 | color: #fff; 65 | } 66 | 67 | .chat-date { 68 | opacity: 0.6; 69 | font-size: 10px; 70 | font-weight: normal; 71 | } 72 | 73 | .content { 74 | padding: 15px 15px; 75 | 76 | .author-name { 77 | font-weight: bold; 78 | margin-bottom: 3px; 79 | font-size: 11px; 80 | } 81 | 82 | > div { 83 | padding-bottom: 20px; 84 | } 85 | 86 | .chat-message { 87 | padding: 5px 10px; 88 | border-radius: 6px; 89 | font-size: 11px; 90 | line-height: 14px; 91 | max-width: 80%; 92 | background: #f3f3f4; 93 | margin-bottom: 10px; 94 | } 95 | 96 | .chat-message.active { 97 | background: #1ab394; 98 | color: #fff; 99 | } 100 | 101 | .left { 102 | text-align: left; 103 | clear: both; 104 | 105 | .chat-message { 106 | float: left; 107 | } 108 | } 109 | 110 | .right { 111 | text-align: right; 112 | clear: both; 113 | 114 | .chat-message { 115 | float: right; 116 | } 117 | 118 | } 119 | 120 | } 121 | 122 | .form-chat { 123 | padding: 10px 10px; 124 | } 125 | 126 | } -------------------------------------------------------------------------------- /app/views/reports/index.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Список отчетов

4 | 12 |
13 |
14 | 15 |
16 |
17 |
18 |
19 |
20 |
Список отчетов
21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | 36 | 37 | 38 | 39 |
40 |
41 |
42 |
43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 |
НаименованиеОписание
1Отчет SLAОтображение заявок, по которым дедлайн был нарушен
59 |
60 | 61 |
62 |
63 |
64 | 65 |
66 |
-------------------------------------------------------------------------------- /app/assets/stylesheets/base/media.scss: -------------------------------------------------------------------------------- 1 | @media (min-width: 768px) { 2 | #page-wrapper { 3 | position: inherit; 4 | margin: 0 0 0 $sidebar-width; 5 | min-height: 1200px; 6 | } 7 | .navbar-static-side { 8 | z-index: 2001; 9 | position: absolute; 10 | width: $sidebar-width; 11 | } 12 | .navbar-top-links .dropdown-messages, 13 | .navbar-top-links .dropdown-tasks, 14 | .navbar-top-links .dropdown-alerts { 15 | margin-left: auto; 16 | } 17 | } 18 | 19 | @media (max-width: 768px) { 20 | #page-wrapper { 21 | position: inherit; 22 | margin: 0 0 0 0px; 23 | min-height: 1000px; 24 | } 25 | .body-small .navbar-static-side { 26 | display: none; 27 | z-index:2001; 28 | position: absolute; 29 | width: 70px; 30 | } 31 | .body-small.mini-navbar .navbar-static-side { 32 | display: block; 33 | } 34 | .lock-word { 35 | display: none; 36 | } 37 | .navbar-form-custom { 38 | display: none; 39 | } 40 | .navbar-header { 41 | display: inline; 42 | float: left; 43 | } 44 | .sidebard-panel { 45 | z-index: 2; 46 | position: relative; 47 | width: auto; 48 | min-height: 100% !important; 49 | } 50 | .sidebar-content .wrapper { 51 | padding-right: 0px; 52 | z-index: 1; 53 | } 54 | .fixed-sidebar.body-small .navbar-static-side { 55 | display: none; 56 | z-index: 2001; 57 | position: fixed; 58 | width: $sidebar-width; 59 | } 60 | .fixed-sidebar.body-small.mini-navbar .navbar-static-side { 61 | display: block; 62 | } 63 | 64 | .ibox-tools { 65 | float: none; 66 | text-align: right; 67 | display: block; 68 | } 69 | } 70 | 71 | @media (max-width: 350px) { 72 | .timeline-item .date { 73 | text-align: left; 74 | width: 110px; 75 | position: relative; 76 | padding-top: 30px; 77 | } 78 | .timeline-item .date i { 79 | position: absolute; 80 | top: 0; 81 | left: 15px; 82 | padding: 5px; 83 | width: 30px; 84 | text-align: center; 85 | border: 1px solid $border-color; 86 | background: #f8f8f8; 87 | } 88 | .timeline-item .content { 89 | border-left: none; 90 | border-top: 1px solid $border-color; 91 | padding-top: 10px; 92 | min-height: 100px; 93 | } 94 | .nav.navbar-top-links li.dropdown { 95 | display: none; 96 | } 97 | 98 | .ibox-tools { 99 | float: none; 100 | text-align: left; 101 | display: inline-block; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /spec/support/database_cleaner.rb: -------------------------------------------------------------------------------- 1 | # Installing database_cleaner: 2 | 3 | # 0. Check spec/support dir is auto-required in spec/rails_helper.rb. 4 | # 5 | # 1. Add database_cleaner to Gemfile: 6 | # 7 | # group :test do 8 | # gem 'database_cleaner' 9 | # end 10 | 11 | # 2. IMPORTANT! Delete the "config.use_transactional_fixtures = ..." line 12 | # in spec/rails_helper.rb (we're going to configure it in this file you're 13 | # reading instead). 14 | 15 | # 3. Create a file like this one you're reading in spec/support/database_cleaner.rb: 16 | RSpec.configure do |config| 17 | 18 | config.use_transactional_fixtures = false 19 | 20 | config.before(:suite) do 21 | if config.use_transactional_fixtures? 22 | 23 | raise(<<-MSG) 24 | 25 | Delete line `config.use_transactional_fixtures = true` from rails_helper.rb 26 | (or set it to false) to prevent uncommitted transactions being used in 27 | JavaScript-dependent specs. 28 | 29 | During testing, the Ruby app server that the JavaScript browser driver 30 | connects to uses a different database connection to the database connection 31 | used by the spec. 32 | 33 | This Ruby app server database connection would not be able to see data that 34 | has been setup by the spec's database connection inside an uncommitted 35 | transaction. 36 | 37 | Disabling the use_transactional_fixtures setting helps avoid uncommitted 38 | transactions in JavaScript-dependent specs, meaning that the Ruby app server 39 | database connection can see any data set up by the specs. 40 | 41 | MSG 42 | 43 | end 44 | end 45 | 46 | config.before(:suite) do 47 | DatabaseCleaner.clean_with(:truncation) 48 | end 49 | 50 | config.before(:each) do 51 | DatabaseCleaner.strategy = :transaction 52 | end 53 | 54 | config.before(:each, type: :feature) do 55 | # :rack_test driver's Rack app under test shares database connection 56 | # with the specs, so we can use transaction strategy for speed. 57 | driver_shares_db_connection_with_specs = Capybara.current_driver == :rack_test 58 | 59 | if driver_shares_db_connection_with_specs 60 | DatabaseCleaner.strategy = :transaction 61 | else 62 | # Non-:rack_test driver is probably a driver for a JavaScript browser 63 | # with a Rack app under test that does *not* share a database 64 | # connection with the specs, so we must use truncation strategy. 65 | DatabaseCleaner.strategy = :truncation 66 | end 67 | end 68 | 69 | config.before(:each) do 70 | DatabaseCleaner.start 71 | end 72 | 73 | config.after(:each) do 74 | DatabaseCleaner.clean 75 | end 76 | 77 | end 78 | -------------------------------------------------------------------------------- /config/deploy/production.rb: -------------------------------------------------------------------------------- 1 | set :stage, :production 2 | set :branch, "master" 3 | set :server_name, "bpm.j123.ru" 4 | set :full_app_name, "#{fetch(:application)}_#{fetch(:stage)}" 5 | server 'jupiter.j123.ru', user: 'mike', roles: %w{web app db}, primary: true 6 | set :deploy_to, "/home/#{fetch(:deploy_user)}/apps/#{fetch(:full_app_name)}" 7 | set :rails_env, :production 8 | set :unicorn_worker_count, 2 9 | set :enable_ssl, false 10 | 11 | # server-based syntax 12 | # ====================== 13 | # Defines a single server with a list of roles and multiple properties. 14 | # You can define all roles on a single server, or split them: 15 | 16 | # server 'example.com', user: 'deploy', roles: %w{app db web}, my_property: :my_value 17 | # server 'example.com', user: 'deploy', roles: %w{app web}, other_property: :other_value 18 | # server 'db.example.com', user: 'deploy', roles: %w{db} 19 | 20 | 21 | 22 | # role-based syntax 23 | # ================== 24 | 25 | # Defines a role with one or multiple servers. The primary server in each 26 | # group is considered to be the first unless any hosts have the primary 27 | # property set. Specify the username and a domain or IP for the server. 28 | # Don't use `:all`, it's a meta role. 29 | 30 | # role :app, %w{deploy@example.com}, my_property: :my_value 31 | # role :web, %w{user1@primary.com user2@additional.com}, other_property: :other_value 32 | # role :db, %w{deploy@example.com} 33 | 34 | 35 | 36 | # Configuration 37 | # ============= 38 | # You can set any configuration variable like in config/deploy.rb 39 | # These variables are then only loaded and set in this stage. 40 | # For available Capistrano configuration variables see the documentation page. 41 | # http://capistranorb.com/documentation/getting-started/configuration/ 42 | # Feel free to add new variables to customise your setup. 43 | 44 | 45 | 46 | # Custom SSH Options 47 | # ================== 48 | # You may pass any option but keep in mind that net/ssh understands a 49 | # limited set of options, consult the Net::SSH documentation. 50 | # http://net-ssh.github.io/net-ssh/classes/Net/SSH.html#method-c-start 51 | # 52 | # Global options 53 | # -------------- 54 | # set :ssh_options, { 55 | # keys: %w(/home/rlisowski/.ssh/id_rsa), 56 | # forward_agent: false, 57 | # auth_methods: %w(password) 58 | # } 59 | # 60 | # The server-based syntax can be used to override options: 61 | # ------------------------------------ 62 | # server 'example.com', 63 | # user: 'user_name', 64 | # roles: %w{web app}, 65 | # ssh_options: { 66 | # user: 'user_name', # overrides user setting above 67 | # keys: %w(/home/user_name/.ssh/id_rsa), 68 | # forward_agent: false, 69 | # auth_methods: %w(publickey password) 70 | # # password: 'please use keys' 71 | # } 72 | -------------------------------------------------------------------------------- /spec/rails_helper.rb: -------------------------------------------------------------------------------- 1 | # This file is copied to spec/ when you run 'rails generate rspec:install' 2 | ENV['RAILS_ENV'] ||= 'test' 3 | require File.expand_path('../../config/environment', __FILE__) 4 | # Prevent database truncation if the environment is production 5 | abort("The Rails environment is running in production mode!") if Rails.env.production? 6 | require 'spec_helper' 7 | require 'rspec/rails' 8 | # Add additional requires below this line. Rails is not loaded until this point! 9 | 10 | # Requires supporting ruby files with custom matchers and macros, etc, in 11 | # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are 12 | # run as spec files by default. This means that files in spec/support that end 13 | # in _spec.rb will both be required and run as specs, causing the specs to be 14 | # run twice. It is recommended that you do not name files matching this glob to 15 | # end with _spec.rb. You can configure this pattern with the --pattern 16 | # option on the command line or in ~/.rspec, .rspec or `.rspec-local`. 17 | # 18 | # The following line is provided for convenience purposes. It has the downside 19 | # of increasing the boot-up time by auto-requiring all files in the support 20 | # directory. Alternatively, in the individual `*_spec.rb` files, manually 21 | # require only the support files necessary. 22 | # 23 | Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } 24 | 25 | # Checks for pending migrations before tests are run. 26 | # If you are not using ActiveRecord, you can remove this line. 27 | ActiveRecord::Migration.maintain_test_schema! 28 | 29 | RSpec.configure do |config| 30 | # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures 31 | config.fixture_path = "#{::Rails.root}/spec/fixtures" 32 | 33 | # If you're not using ActiveRecord, or you'd prefer not to run each of your 34 | # examples within a transaction, remove the following line or assign false 35 | # instead of true. 36 | config.use_transactional_fixtures = false 37 | 38 | # RSpec Rails can automatically mix in different behaviours to your tests 39 | # based on their file location, for example enabling you to call `get` and 40 | # `post` in specs under `spec/controllers`. 41 | # 42 | # You can disable this behaviour by removing the line below, and instead 43 | # explicitly tag your specs with their type, e.g.: 44 | # 45 | # RSpec.describe UsersController, :type => :controller do 46 | # # ... 47 | # end 48 | # 49 | # The different available types are documented in the features, such as in 50 | # https://relishapp.com/rspec/rspec-rails/docs 51 | config.infer_spec_type_from_file_location! 52 | 53 | config.before(:suite) do 54 | Rails.application.load_seed # loading seeds 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /app/views/req_workgroups/edit.html.erb: -------------------------------------------------------------------------------- 1 | <%= req_edit_header("Редактировать рабочую группу", "req_workgroups", "Рабочие группы", "Рабочая группа") %> 2 |
3 |
4 |
5 |
6 |
7 |
Редактирование рабочей группы
8 | 16 |
17 |
18 | <%= render 'shared/actions_and_assignees' %> 19 |
20 | <%= simple_form_for(@req) do |f| %> 21 | <%= f.input :id, disabled: true %> 22 | <%= f.input :state, disabled: true %> 23 | <%= f.input :name, disabled: @req.is_disabled?("name") %> 24 | <%= f.input :description, disabled: @req.is_disabled?("description") %> 25 | <%= f.input :money, disabled: @req.is_disabled?("money") %> 26 |
27 |

Члены рабочей группы

28 |
29 |
30 | Операции 31 |
32 |
33 | <%= InfWorkgroupMember.human_attribute_name("user_id") %> 34 |
35 |
36 | Признак руководителя РГ 37 |
38 |
39 | <%= InfWorkgroupMember.human_attribute_name("comment") %> 40 |
41 |
42 | <%= f.simple_fields_for :inf_workgroup_members do |p| %> 43 | <%= render 'inf_workgroup_member_fields', f: p %> 44 | <% end %> 45 | 48 |
49 |
50 | <%= render 'shared/req_edit_buttons', f: f %> 51 | <% end %> 52 |
53 |
54 |
55 |
56 |
57 | -------------------------------------------------------------------------------- /app/views/req_rolepurchases/show.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Просмотр заявки на закупку (с ролями)

4 | 15 |
16 |
17 | 18 |
19 |
20 |
21 |
22 |
23 | 27 |
28 |
29 |
30 | <%= render 'shared/actions_and_assignees' %> 31 |
32 |
33 | 34 |

<%= @req.id %>

35 |
36 |
37 | 38 |

<%= @req.state %>

39 |
40 |
41 | 42 |

<%= @req.name %>

43 |
44 |
45 | 46 |

<%= number_to_currency(@req.money, locale: :ru) %>

47 |
48 | <% if @req.is_assigned?(current_user) %> 49 |
50 | <%= link_to 'Редактировать', edit_req_rolepurchase_path(@req), class: "btn btn-primary" %> 51 |
52 | <% end %> 53 |
54 |
55 | <%= render 'shared/history_tab' %> 56 |
57 |
58 |
59 |
60 |
61 |
62 | -------------------------------------------------------------------------------- /app/views/layouts/_nav.html.erb: -------------------------------------------------------------------------------- 1 |
2 | 64 |
-------------------------------------------------------------------------------- /app/models/req_rolepurchase.rb: -------------------------------------------------------------------------------- 1 | class ReqRolepurchase < ActiveRecord::Base 2 | include ReqMain 3 | after_initialize :init 4 | after_create :set_assignee 5 | has_many :assignments, as: :assignable 6 | validates :money, presence: true 7 | validates :name, presence: true 8 | belongs_to :last_user, class_name: "User" 9 | has_many :history, as: :historyable 10 | attr_accessor :assign_user_id 11 | validate :has_client_manager 12 | 13 | state_machine :initial => :new do 14 | before_transition :new => :wait_approval, :do => :create_assignments 15 | after_transition :wait_approval => :approved, :do => :approve_assignment 16 | after_transition :wait_approval => :disapproved, :do => :disapprove_assignment 17 | after_transition any => any, :do => :write_history 18 | 19 | event :initiate do 20 | transition :new => :wait_approval 21 | end 22 | 23 | event :approve do 24 | transition :wait_approval => :approved 25 | end 26 | 27 | event :disapprove do 28 | transition :wait_approval => :disapproved 29 | end 30 | 31 | state :finish_approved 32 | state :finish_disapproved 33 | 34 | end 35 | 36 | def users_list 37 | User.joins("JOIN users_roles ur on ur.user_id = users.id 38 | JOIN roles r on r.id = ur.role_id").where("r.code = ?", "client_manager")#.order(:name) 39 | end 40 | 41 | private 42 | 43 | def init 44 | self.state ||= 'new' 45 | # set false to show field for state in edit form 46 | @disabled = Hash.new{|hash, key| hash[key] = Hash.new} 47 | @disabled["new"]["name"] = false 48 | @disabled["new"]["money"] = false 49 | @disabled["wait_approval"]["name"] = false 50 | @disabled["wait_approval"]["money"] = false 51 | end 52 | 53 | def create_assignments 54 | Rails.logger.info('!!!!! create_assignments') 55 | Rails.logger.info("!!!!! assign_user_id #{@assign_user_id}") 56 | Rails.logger.info("!!!!! last_user_id #{last_user_id}") 57 | close_assignment(self.last_user_id) 58 | new_assignment(@assign_user_id) if !@assign_user_id.blank? 59 | end 60 | 61 | def approve_assignment 62 | Rails.logger.info('!!! approve_assignment') 63 | current_assignment = self.assignments.where(closed: false, user_id: self.last_user_id).first 64 | current_assignment.update_attributes(closed: true, result: 'approved') if !current_assignment.nil? 65 | self.update_attributes(state: 'finish_approved') 66 | end 67 | 68 | def disapprove_assignment 69 | Rails.logger.info('!!! disapprove_assignment') 70 | current_assignment = self.assignments.where(closed: false, user_id: self.last_user_id).first 71 | current_assignment.update_attributes(closed: true, result: 'disapproved') if !current_assignment.nil? 72 | self.update_attributes(state: 'finish_disapproved') 73 | end 74 | 75 | #validations 76 | 77 | def has_client_manager 78 | # Rails.logger.info('!!!!! one_group_leader') 79 | # Rails.logger.info(self.inf_workgroup_members.where(main: true).count) 80 | if self.state == 'wait_approval' and @assign_user_id.blank? 81 | errors.add(:assign_user_id, :validate_has_client_manager) 82 | end 83 | end 84 | 85 | end 86 | -------------------------------------------------------------------------------- /vendor/assets/javascripts/metisMenu/jquery.metisMenu.js: -------------------------------------------------------------------------------- 1 | /* 2 | * metismenu - v2.0.2 3 | * A jQuery menu plugin 4 | * https://github.com/onokumus/metisMenu 5 | * 6 | * Made by Osman Nuri Okumus 7 | * Under MIT License 8 | */ 9 | 10 | !function(a){"use strict";function b(){var a=document.createElement("mm"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}function c(b){return this.each(function(){var c=a(this),d=c.data("mm"),f=a.extend({},e.DEFAULTS,c.data(),"object"==typeof b&&b);d||c.data("mm",d=new e(this,f)),"string"==typeof b&&d[b]()})}a.fn.emulateTransitionEnd=function(b){var c=!1,e=this;a(this).one("mmTransitionEnd",function(){c=!0});var f=function(){c||a(e).trigger(d.end)};return setTimeout(f,b),this};var d=b();d&&(a.event.special.mmTransitionEnd={bindType:d.end,delegateType:d.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}});var e=function(b,c){this.$element=a(b),this.options=a.extend({},e.DEFAULTS,c),this.transitioning=null,this.init()};e.TRANSITION_DURATION=350,e.DEFAULTS={toggle:!0,doubleTapToGo:!1,activeClass:"active"},e.prototype.init=function(){var b=this,c=this.options.activeClass;this.$element.find("li."+c).has("ul").children("ul").addClass("collapse in"),this.$element.find("li").not("."+c).has("ul").children("ul").addClass("collapse"),this.options.doubleTapToGo&&this.$element.find("li."+c).has("ul").children("a").addClass("doubleTapToGo"),this.$element.find("li").has("ul").children("a").on("click.metisMenu",function(d){var e=a(this),f=e.parent("li"),g=f.children("ul");return d.preventDefault(),f.hasClass(c)?b.hide(g):b.show(g),b.options.doubleTapToGo&&b.doubleTapToGo(e)&&"#"!==e.attr("href")&&""!==e.attr("href")?(d.stopPropagation(),void(document.location=e.attr("href"))):void 0})},e.prototype.doubleTapToGo=function(a){var b=this.$element;return a.hasClass("doubleTapToGo")?(a.removeClass("doubleTapToGo"),!0):a.parent().children("ul").length?(b.find(".doubleTapToGo").removeClass("doubleTapToGo"),a.addClass("doubleTapToGo"),!1):void 0},e.prototype.show=function(b){var c=this.options.activeClass,f=a(b),g=f.parent("li");if(!this.transitioning&&!f.hasClass("in")){g.addClass(c),this.options.toggle&&this.hide(g.siblings().children("ul.in")),f.removeClass("collapse").addClass("collapsing").height(0),this.transitioning=1;var h=function(){f.removeClass("collapsing").addClass("collapse in").height(""),this.transitioning=0};return d?void f.one("mmTransitionEnd",a.proxy(h,this)).emulateTransitionEnd(e.TRANSITION_DURATION).height(f[0].scrollHeight):h.call(this)}},e.prototype.hide=function(b){var c=this.options.activeClass,f=a(b);if(!this.transitioning&&f.hasClass("in")){f.parent("li").removeClass(c),f.height(f.height())[0].offsetHeight,f.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var g=function(){this.transitioning=0,f.removeClass("collapsing").addClass("collapse")};return d?void f.height(0).one("mmTransitionEnd",a.proxy(g,this)).emulateTransitionEnd(e.TRANSITION_DURATION):g.call(this)}};var f=a.fn.metisMenu;a.fn.metisMenu=c,a.fn.metisMenu.Constructor=e,a.fn.metisMenu.noConflict=function(){return a.fn.metisMenu=f,this}}(jQuery); -------------------------------------------------------------------------------- /app/assets/stylesheets/base/top_navigation.scss: -------------------------------------------------------------------------------- 1 | .top-navigation #page-wrapper { 2 | margin-left: 0; 3 | } 4 | 5 | 6 | .top-navigation .navbar-nav .dropdown-menu > .active > a { 7 | background: white; 8 | color: $navy; 9 | font-weight: bold; 10 | } 11 | 12 | .white-bg .navbar-fixed-top, .white-bg .navbar-static-top { 13 | background: #fff; 14 | } 15 | 16 | .top-navigation .navbar { 17 | margin-bottom: 0; 18 | } 19 | 20 | .top-navigation .nav > li > a { 21 | padding: 15px 20px; 22 | color: #676a6c; 23 | } 24 | 25 | .top-navigation .nav > li a:hover, .top-navigation .nav > li a:focus { 26 | background: #fff; 27 | color: $navy; 28 | } 29 | 30 | .top-navigation .nav > li.active { 31 | background: #fff; 32 | border: none; 33 | } 34 | .top-navigation .nav > li.active > a { 35 | color: $navy; 36 | } 37 | .top-navigation .navbar-right { 38 | margin-right: 10px; 39 | } 40 | 41 | .top-navigation .navbar-nav .dropdown-menu { 42 | box-shadow: none; 43 | border: 1px solid #e7eaec; 44 | } 45 | 46 | .top-navigation .dropdown-menu > li > a { 47 | margin: 0; 48 | padding: 7px 20px; 49 | } 50 | 51 | .navbar .dropdown-menu { 52 | margin-top: 0px; 53 | } 54 | 55 | .top-navigation .navbar-brand { 56 | background: $navy; 57 | color: #fff; 58 | padding: 15px 25px; 59 | } 60 | 61 | .top-navigation .navbar-top-links li:last-child { 62 | margin-right: 0; 63 | } 64 | 65 | .top-navigation.mini-navbar #page-wrapper, 66 | .top-navigation.body-small.fixed-sidebar.mini-navbar #page-wrapper, 67 | .mini-navbar .top-navigation #page-wrapper, 68 | .body-small.fixed-sidebar.mini-navbar .top-navigation #page-wrapper, 69 | .canvas-menu #page-wrapper { 70 | margin: 0; 71 | } 72 | 73 | .top-navigation.fixed-nav #wrapper, .fixed-nav #wrapper.top-navigation { 74 | margin-top: 50px; 75 | } 76 | 77 | .top-navigation .footer.fixed { 78 | margin-left: 0 !important; 79 | } 80 | 81 | .top-navigation .wrapper.wrapper-content { 82 | padding: 40px; 83 | } 84 | .top-navigation.body-small .wrapper.wrapper-content, .body-small .top-navigation .wrapper.wrapper-content { 85 | padding: 40px 0px 40px 0px; 86 | } 87 | 88 | .navbar-toggle { 89 | background-color: $navy; 90 | color: #fff; 91 | padding: 6px 12px; 92 | font-size: 14px; 93 | } 94 | 95 | .top-navigation .navbar-nav .open .dropdown-menu > li > a, .top-navigation .navbar-nav .open .dropdown-menu .dropdown-header { 96 | padding: 10px 15px 10px 20px; 97 | } 98 | 99 | @media (max-width: 768px) { 100 | .top-navigation .navbar-header { 101 | display: block; 102 | float: none; 103 | } 104 | } 105 | 106 | .menu-visible-lg, .menu-visible-md { 107 | display: none !important; 108 | } 109 | 110 | @media (min-width: 1200px) { 111 | .menu-visible-lg { 112 | display: block !important; 113 | } 114 | } 115 | @media (min-width: 992px) { 116 | .menu-visible-md { 117 | display: block !important; 118 | } 119 | } 120 | 121 | @media (max-width: 767px) { 122 | .menu-visible-md { 123 | display: block !important; 124 | } 125 | .menu-visible-lg { 126 | display: block !important; 127 | } 128 | } -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | # PostgreSQL. Versions 8.2 and up are supported. 2 | # 3 | # Install the pg driver: 4 | # gem install pg 5 | # On OS X with Homebrew: 6 | # gem install pg -- --with-pg-config=/usr/local/bin/pg_config 7 | # On OS X with MacPorts: 8 | # gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config 9 | # On Windows: 10 | # gem install pg 11 | # Choose the win32 build. 12 | # Install PostgreSQL and put its /bin directory on your path. 13 | # 14 | # Configure Using Gemfile 15 | # gem 'pg' 16 | # 17 | default: &default 18 | adapter: postgresql 19 | encoding: unicode 20 | # For details on connection pooling, see rails configuration guide 21 | # http://guides.rubyonrails.org/configuring.html#database-pooling 22 | pool: 5 23 | 24 | development: 25 | <<: *default 26 | database: bpm_dev 27 | username: first 28 | password: asdfg 29 | host: localhost 30 | 31 | # The specified database role being used to connect to postgres. 32 | # To create additional roles in postgres see `$ createuser --help`. 33 | # When left blank, postgres will use the default role. This is 34 | # the same name as the operating system user that initialized the database. 35 | #username: bpm 36 | 37 | # The password associated with the postgres role (username). 38 | #password: 39 | 40 | # Connect on a TCP socket. Omitted by default since the client uses a 41 | # domain socket that doesn't need configuration. Windows does not have 42 | # domain sockets, so uncomment these lines. 43 | #host: localhost 44 | 45 | # The TCP port the server listens on. Defaults to 5432. 46 | # If your server runs on a different port number, change accordingly. 47 | #port: 5432 48 | 49 | # Schema search path. The server defaults to $user,public 50 | #schema_search_path: myapp,sharedapp,public 51 | 52 | # Minimum log levels, in increasing order: 53 | # debug5, debug4, debug3, debug2, debug1, 54 | # log, notice, warning, error, fatal, and panic 55 | # Defaults to warning. 56 | #min_messages: notice 57 | 58 | # Warning: The database defined as "test" will be erased and 59 | # re-generated from your development database when you run "rake". 60 | # Do not set this db to the same as development or production. 61 | test: 62 | <<: *default 63 | database: bpm_test 64 | 65 | # As with config/secrets.yml, you never want to store sensitive information, 66 | # like your database password, in your source code. If your source code is 67 | # ever seen by anyone, they now have access to your database. 68 | # 69 | # Instead, provide the password as a unix environment variable when you boot 70 | # the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database 71 | # for a full rundown on how to provide these environment variables in a 72 | # production deployment. 73 | # 74 | # On Heroku and other platform providers, you may have a full connection URL 75 | # available as an environment variable. For example: 76 | # 77 | # DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase" 78 | # 79 | # You can use this database configuration with: 80 | # 81 | # production: 82 | # url: <%= ENV['DATABASE_URL'] %> 83 | # 84 | production: 85 | <<: *default 86 | database: bpm_production 87 | username: bpm 88 | password: <%= ENV['BPM_DATABASE_PASSWORD'] %> 89 | -------------------------------------------------------------------------------- /app/views/req_purchases/show.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Просмотр заявки на закупку

4 | 15 |
16 |
17 | 18 |
19 |
20 |
21 |
22 |
23 | 27 |
28 |
29 |
30 | <%= render 'shared/actions_and_assignees' %> 31 |
32 |
33 | 34 |

<%= @req.id %>

35 |
36 |
37 | 38 |

<%= @req.state %>

39 |
40 |
41 | 42 |

<%= @req.name %>

43 |
44 |
45 | 46 |

<%= number_to_currency(@req.money, locale: :ru) %>

47 |
48 |
49 | 50 | <% if @req.myfile? %> 51 |

<%= link_to(@req.myfile_identifier, @req.myfile.url) %>

52 | <% else %> 53 |

Файла нет

54 | <% end %> 55 |
56 | <% if @req.is_assigned?(current_user) %> 57 |
58 | <%= link_to 'Редактировать', edit_req_purchase_path(@req), class: "btn btn-primary" %> 59 |
60 | <% end %> 61 |
62 |
63 | <%= render 'shared/history_tab' %> 64 |
65 |
66 |
67 |
68 |
69 |
70 | -------------------------------------------------------------------------------- /config/deploy/shared/database.yml.erb: -------------------------------------------------------------------------------- 1 | # PostgreSQL. Versions 8.2 and up are supported. 2 | # 3 | # Install the pg driver: 4 | # gem install pg 5 | # On OS X with Homebrew: 6 | # gem install pg -- --with-pg-config=/usr/local/bin/pg_config 7 | # On OS X with MacPorts: 8 | # gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config 9 | # On Windows: 10 | # gem install pg 11 | # Choose the win32 build. 12 | # Install PostgreSQL and put its /bin directory on your path. 13 | # 14 | # Configure Using Gemfile 15 | # gem 'pg' 16 | # 17 | default: &default 18 | adapter: postgresql 19 | encoding: unicode 20 | # For details on connection pooling, see rails configuration guide 21 | # http://guides.rubyonrails.org/configuring.html#database-pooling 22 | pool: 5 23 | 24 | development: 25 | <<: *default 26 | database: testcap_dev 27 | # username: postgres 28 | # password: terra-123 29 | username: first 30 | password: asdfg 31 | host: localhost 32 | 33 | # The specified database role being used to connect to postgres. 34 | # To create additional roles in postgres see `$ createuser --help`. 35 | # When left blank, postgres will use the default role. This is 36 | # the same name as the operating system user that initialized the database. 37 | #username: testcap 38 | 39 | # The password associated with the postgres role (username). 40 | #password: 41 | 42 | # Connect on a TCP socket. Omitted by default since the client uses a 43 | # domain socket that doesn't need configuration. Windows does not have 44 | # domain sockets, so uncomment these lines. 45 | #host: localhost 46 | 47 | # The TCP port the server listens on. Defaults to 5432. 48 | # If your server runs on a different port number, change accordingly. 49 | #port: 5432 50 | 51 | # Schema search path. The server defaults to $user,public 52 | #schema_search_path: myapp,sharedapp,public 53 | 54 | # Minimum log levels, in increasing order: 55 | # debug5, debug4, debug3, debug2, debug1, 56 | # log, notice, warning, error, fatal, and panic 57 | # Defaults to warning. 58 | #min_messages: notice 59 | 60 | # Warning: The database defined as "test" will be erased and 61 | # re-generated from your development database when you run "rake". 62 | # Do not set this db to the same as development or production. 63 | test: 64 | <<: *default 65 | database: testcap_test 66 | 67 | # As with config/secrets.yml, you never want to store sensitive information, 68 | # like your database password, in your source code. If your source code is 69 | # ever seen by anyone, they now have access to your database. 70 | # 71 | # Instead, provide the password as a unix environment variable when you boot 72 | # the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database 73 | # for a full rundown on how to provide these environment variables in a 74 | # production deployment. 75 | # 76 | # On Heroku and other platform providers, you may have a full connection URL 77 | # available as an environment variable. For example: 78 | # 79 | # DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase" 80 | # 81 | # You can use this database configuration with: 82 | # 83 | # production: 84 | # url: <%= ENV['DATABASE_URL'] %> 85 | # 86 | production: 87 | <<: *default 88 | database: testcap_production 89 | username: testcap 90 | password: <%= ENV['TESTCAP_DATABASE_PASSWORD'] %> 91 | -------------------------------------------------------------------------------- /lib/req_main.rb: -------------------------------------------------------------------------------- 1 | module ReqMain 2 | def is_assigned?(user_id) 3 | self.assignments.where(closed: false, user_id: user_id).first.nil? ? false : true 4 | end 5 | 6 | def opened_assignment_users 7 | assignments = self.assignments.where(closed: false) 8 | Rails.logger.info('!!!!! opened_assignment_users') 9 | Rails.logger.info(assignments.count) 10 | if assignments.count > 0 11 | assignments.map {|x| x.user.name }.join(', ') 12 | else 13 | "" 14 | end 15 | end 16 | 17 | def is_disabled?(field) 18 | res = @disabled[self.state][field] 19 | res = true if res.nil? 20 | res 21 | end 22 | 23 | def set_last_user(user) 24 | self.last_user_id = user.id 25 | end 26 | 27 | private 28 | 29 | def set_assignee 30 | # user_id ||= User.where("email = ?", "admin@test.co").first.id 31 | self.assignments.create(user_id: self.last_user_id, description: self.name) 32 | end 33 | 34 | def close_assignment(user_id, result = 'ok') 35 | Rails.logger.info('!!!!! close_assignment') 36 | Rails.logger.info(user_id) 37 | current_assignment = self.assignments.where(closed: false, user_id: user_id).first 38 | current_assignment.update_attributes(closed: true, close_date: Time.now, result: result) if !current_assignment.nil? 39 | end 40 | 41 | def new_assignment(user_id) 42 | Rails.logger.info('!!!!! new_assignment') 43 | opened_assignments = self.assignments.where(closed: false, user_id: user_id).count 44 | if opened_assignments == 0 45 | new_assignment = self.assignments.create(user_id: user_id, description: self.name, 46 | deadline_date: sla_deadline_date, notify_before_date: sla_notify_before_date, 47 | notify_after_date: sla_notify_after_date) 48 | end 49 | end 50 | 51 | def write_history 52 | Rails.logger.info('!!!!! write_history') 53 | text = self.last_user.name + I18n.t(:changed_state_to) + self.state 54 | self.history.create(state: self.state, user_id: self.last_user_id, description: text, 55 | new_values: 'TO DO') 56 | end 57 | 58 | def sla_deadline_date 59 | Rails.logger.info('!!!!! sla_deadline_date before if, days, state') 60 | if !@sla.nil? 61 | days = @sla[self.state]["deadline"] 62 | Rails.logger.info("#{days}, #{self.state}") 63 | res = days.blank? ? nil : Time.now + (days*24*60*60) 64 | end 65 | res 66 | end 67 | 68 | def sla_notify_before_date 69 | Rails.logger.info('!!!!! sla_notify_before_date before if, hours') 70 | if !@sla.nil? && sla_deadline_date 71 | hours = @sla[self.state]["notify_before"] 72 | Rails.logger.info(hours) 73 | res = hours.blank? ? nil : sla_deadline_date - (hours*60*60) 74 | end 75 | res 76 | end 77 | 78 | def sla_notify_after_date 79 | Rails.logger.info('!!!!! sla_notify_after_date before if, hours') 80 | if !@sla.nil? && sla_deadline_date 81 | hours = @sla[self.state]["notify_after"] 82 | Rails.logger.info(hours) 83 | res = hours.blank? ? nil : sla_deadline_date + (hours*60*60) 84 | end 85 | res 86 | end 87 | 88 | def has_opened_assignments? 89 | Rails.logger.info('!!! has_opened_assignments') 90 | assignments = self.assignments.where(closed: false) 91 | Rails.logger.info(assignments.count) 92 | if assignments.count > 0 93 | true 94 | else 95 | false 96 | end 97 | end 98 | 99 | end -------------------------------------------------------------------------------- /app/views/req_workgroups/index.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Список рабочих групп

4 | 12 |
13 |
14 | 15 |
16 |
17 |
18 |
19 |
20 |
Открытые рабочие группы
21 | 29 |
30 |
31 |
32 | <%= link_to t(:new_req), new_req_workgroup_path, class: "btn btn-primary"%> 33 |
34 |
35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | <% @reqs.each do |req| %> 50 | 51 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | <% end %> 65 | 66 |
<%= ReqWorkgroup.human_attribute_name("id") %><%= ReqWorkgroup.human_attribute_name("state") %><%= t(:curr_user) %><%= ReqWorkgroup.human_attribute_name("name") %><%= ReqWorkgroup.human_attribute_name("description") %><%= ReqWorkgroup.human_attribute_name("money") %><%= ReqWorkgroup.human_attribute_name("last_user_id") %>
52 | <% if req.is_assigned?(current_user) %> 53 | 54 | <% end %> 55 | <%= link_to req.id, req %><%= req.state %><%= req.opened_assignment_users %><%= req.name %><%= req.description %><%= number_to_currency(req.money, locale: :ru) %><%= req.last_user.name unless req.last_user.nil?%>
67 |
68 |
69 |
70 |
71 |
72 |
73 | 74 | -------------------------------------------------------------------------------- /app/views/req_purchases/index.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Заявки на закупку

4 | 12 |
13 |
14 | 15 |
16 |
17 |
18 |
19 |
20 |
Открытые заявки на закупку
21 | 29 |
30 |
31 |
32 | <%= link_to t(:new_req), new_req_purchase_path, class: "btn btn-primary"%> 33 |
34 |
35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | <% @reqs.each do |req| %> 49 | 50 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | <% end %> 63 | 64 |
<%= ReqPurchase.human_attribute_name("id") %><%= ReqPurchase.human_attribute_name("state") %><%= t(:curr_user) %><%= ReqPurchase.human_attribute_name("name") %>
<%= ReqPurchase.human_attribute_name("money") %>
<%= ReqPurchase.human_attribute_name("last_user_id") %>
51 | <% if req.is_assigned?(current_user) %> 52 | 53 | <% end %> 54 | <%= link_to req.id, req %><%= req.state %><%= req.opened_assignment_users %><%= req.name %><%= number_to_currency(req.money, :unit => "") %><%= req.last_user.name unless req.last_user.nil?%>
65 |
66 |
67 |
68 |
69 |
70 |
71 | 72 | 77 | 78 | -------------------------------------------------------------------------------- /app/views/req_rolepurchases/index.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Заявки на закупку (с ролями)

4 | 12 |
13 |
14 | 15 |
16 |
17 |
18 |
19 |
20 |
Открытые заявки на закупку
21 | 29 |
30 |
31 |
32 | <%= link_to t(:new_req), new_req_rolepurchase_path, class: "btn btn-primary"%> 33 |
34 |
35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | <% @reqs.each do |req| %> 49 | 50 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | <% end %> 63 | 64 |
<%= ReqRolepurchase.human_attribute_name("id") %><%= ReqRolepurchase.human_attribute_name("state") %><%= t(:curr_user) %><%= ReqRolepurchase.human_attribute_name("name") %>
<%= ReqRolepurchase.human_attribute_name("money") %>
<%= ReqRolepurchase.human_attribute_name("last_user_id") %>
51 | <% if req.is_assigned?(current_user) %> 52 | 53 | <% end %> 54 | <%= link_to req.id, req %><%= req.state %><%= req.opened_assignment_users %><%= req.name %><%= number_to_currency(req.money, :unit => "") %><%= req.last_user.name unless req.last_user.nil?%>
65 |
66 |
67 |
68 |
69 |
70 |
71 | 72 | 77 | 78 | -------------------------------------------------------------------------------- /app/views/req_reassigns/show.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Просмотр заявки на перезакрепление

4 | 15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | 26 |
27 |
28 |
29 | <%= render 'shared/actions_and_assignees' %> 30 |
31 |
32 | 33 |

<%= @req.id %>

34 |
35 |
36 | 37 |

<%= @req.state %>

38 |
39 |
40 | 41 |

<%= @req.name %>

42 |
43 |
44 | 45 |

<%= @req.client.name %>

46 |
47 |
48 | 49 |

<%= @req.old_manager.name %>

50 |
51 |
52 | 53 |

<%= @req.new_manager.name %>

54 |
55 |
56 | 57 |

<%= number_to_currency(@req.money) %>

58 |
59 |
60 | 61 |

<%= @req.info %>

62 |
63 | <% if @req.is_assigned?(current_user) %> 64 |
65 | <%= link_to 'Редактировать', edit_req_reassign_path(@req), class: "btn btn-primary" %> 66 |
67 | <% end %> 68 |
69 |
70 | <%= render 'shared/history_tab' %> 71 |
72 |
73 |
74 |
75 |
76 |
77 | -------------------------------------------------------------------------------- /app/views/users/index.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Список пользователей

4 | 12 |
13 |
14 | 15 |
16 |
17 |
18 |
19 |
20 |
Список пользователей
21 | 29 |
30 |
31 |
32 | <%= link_to 'Тут кнопка добавления нового пользователя', '#', class: "btn btn-primary"%> 33 |
34 |
35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | <% @users.each do |user| %> 50 | 51 | 54 | 55 | 56 | 57 | 58 | 59 | 64 | 69 | 70 | <% end %> 71 | 72 |
<%= User.human_attribute_name("id") %><%= User.human_attribute_name("name") %><%= User.human_attribute_name("email") %>Роли пользователя<%= User.human_attribute_name("unit_id") %><%= User.human_attribute_name("deleted") %><%= User.human_attribute_name("admin") %>
52 | 53 | <%= user.id %><%= user.name %><%= user.email %><%= user.roles.map {|x| x.name }.join(', ') %><%= user.unit.name if user.unit%> 60 | <% if user.deleted == true %> 61 | 62 | <% end %> 63 | 65 | <% if user.admin == true %> 66 | 67 | <% end %> 68 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | -------------------------------------------------------------------------------- /app/views/req_reassigns/index.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Заявки на перезакрепление

4 | 12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
Открытые заявки на перезакрепление
20 | 28 |
29 |
30 |
31 | <%= link_to t(:new_req), new_req_reassign_path, class: "btn btn-primary"%> 32 |
33 |
34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | <% @reqs.each do |req| %> 49 | 50 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | <% end %> 64 | 65 |
<%= ReqReassign.human_attribute_name("id") %><%= ReqReassign.human_attribute_name("state") %><%= t(:curr_user) %><%= ReqReassign.human_attribute_name("name") %><%= ReqReassign.human_attribute_name("old_manager_id") %><%= ReqReassign.human_attribute_name("new_manager_id") %>
<%= ReqReassign.human_attribute_name("money") %>
51 | <% if req.is_assigned?(current_user) %> 52 | 53 | <% end %> 54 | <%= link_to req.id, req %><%= req.state %><%= req.opened_assignment_users %><%= req.client.name %><%= req.old_manager.name %><%= req.new_manager.name %><%= number_to_currency(req.money, :unit => "") %>
66 |
67 |
68 |
69 |
70 |
71 |
72 | 73 | 78 | 79 | -------------------------------------------------------------------------------- /app/views/assignments/index.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Список заданий

4 | 12 |
13 |
14 | 15 |
16 |
17 |
18 |
19 |
20 |
Задачи назначенные мне
21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | 36 | 37 | 38 | 39 |
40 |
41 |
42 |
43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | <% @assignments.each do |ass| %> 56 | 57 | 64 | 65 | 66 | 67 | 68 | 73 | 74 | <% end %> 75 | 76 |
<%= Assignment.human_attribute_name("id") %><%= Assignment.human_attribute_name("user_id") %>Тип задания<%= Assignment.human_attribute_name("description") %><%= Assignment.human_attribute_name("closed") %>
58 | <% if ass.closed != true %> 59 | <%= link_to [:edit, ass.assignable], class: "icon-block" do %> 60 | 61 | <% end %> 62 | <% end %> 63 | <%= link_to ass.id, ass.assignable %><%= ass.user.name %><%= ass.assignable_type %><%= ass.description %> 69 | <% if ass.closed == true %> 70 | 71 | <% end %> 72 |
77 |
78 | 79 |
80 |
81 |
82 | 83 |
84 |
-------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BPM on Rails - Business Process Management System 2 | 3 | ## Purpose of the System 4 | 5 | BPM on Rails is Framework for business process automatisation. Built on top of Ruby on Rails it leverages all power of Ruby on Rails and make it super easy to set up business processes with necessary states, actors and data. 6 | 7 | **It is good alternative for such BPM systems as Pega BPM or IBM**. 8 | 9 | Example of business process for automatisation described here - [ReqReassign_state.png](https://raw.githubusercontent.com/klishevich/bpm/master/ReqReassign_state.png) 10 | 11 | ## Functionality realized 12 | 13 | * *Multiprocess* - you could add several processes and all they will be displayed in one list - assignments list 14 | * *Parallel assignments* - on each state task could be assigned to several users 15 | * *Dashboard* - home screen contain dashboard where all most important information is displayed as: new tasks, tasks with deadline, graphs, news feed 16 | * *Nested forms* - forms which contain nested data, for example, purchase list 17 | * *Notifications* - sending notifications for tasks being assigned and tasks being closed 18 | * *Organisation structure* - dictionary to store employees and there hierarchy, which is used to define assignee for tasks 19 | * *Roles* - each user could be assigned for several roles, and according to the roles user have, logic of assignment could be realised 20 | * *Admin interface* - user with admin role could do some actions (assign roles to users) 21 | * *History of change* - history of process is stored and contain following information: user, date of change, state, description 22 | * *Reports* - allow you to make you own business specific reports, for now SLA Report is made. 23 | * *Mobile Adaptive* - mobile adaptive theme is used, so usage from mobile devices is very comfortable. 24 | * *Work with Files* - files could be attached, deleted, and downloaded 25 | * *Tests* - RSpec integration test are made for 2 processes 26 | 27 | **All described functionality has reference implementation** in following classes: ReqPurchase, ReqReassign, ReqRolepurchase, ReqWorkgroup 28 | 29 | Module ReqMain contains base functionality for process routing. 30 | 31 | ## Naming conventions 32 | 33 | All classes which describe process should name Req… (ReqPurchase for ex.) 34 | All classes which contain additional data for some process should name Inf + Process name + Data name (InfWorkgroupMember for ReqWorkgroup) 35 | 36 | ## Future 37 | 38 | I am developing BPM on Rails, and going to continue its development 39 | 40 | ## Cooperation 41 | 42 | I am opened for cooperation in BPM on Rails development, just email me info@busation.com or tweet me @busation 43 | 44 | # BPM on Rails - Система управление бизнес-процессами 45 | 46 | ## Назначение системы 47 | 48 | Система - является платформой для автоматизации бизнес-процессов предприятия. На базе BPM on Rails можно быстро автоматизировать бизнес процессы (процессы согласования, управление взаимоотношения с клиентами, автоматизация документооборота и т.п.). 49 | Пример процесса для автоматизации - [ReqReassign_state.png](https://raw.githubusercontent.com/klishevich/bpm/master/ReqReassign_state.png) 50 | 51 | ## Загрузка оргструктуры предприятия 52 | 53 | Для загрузки оргструктуры необходимо подготовить csv-файл следующего вида - [OgrStructureImport.csv](https://raw.githubusercontent.com/klishevich/bpm/master/db/import/OgrStructureImport.csv). После этого необходимо выполнить следующий код из seeds.rb: 54 | ```ruby 55 | CSV.foreach("db/import/OgrStructureImport.csv", { encoding: "UTF-8", headers: true, 56 | header_converters: :symbol, converters: :all, :col_sep => ";" }) do |row| 57 | Unit.create(row.to_hash) if !row.field(1).blank? 58 | end 59 | ``` 60 | 61 | ## Загрузка пользователей 62 | 63 | Производится аналогично загрузке оргструктуры, формат файла для загрузки - [UsersImport.csv](https://raw.githubusercontent.com/klishevich/bpm/master/db/import/UsersImport.csv). 64 | 65 | -------------------------------------------------------------------------------- /config/environments/production.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # Code is not reloaded between requests. 5 | config.cache_classes = true 6 | 7 | # Eager load code on boot. This eager loads most of Rails and 8 | # your application in memory, allowing both threaded web servers 9 | # and those relying on copy on write to perform better. 10 | # Rake tasks automatically ignore this option for performance. 11 | config.eager_load = true 12 | 13 | # Full error reports are disabled and caching is turned on. 14 | config.consider_all_requests_local = false 15 | config.action_controller.perform_caching = true 16 | 17 | config.i18n.default_locale = :ru 18 | config.i18n.available_locales = :ru 19 | 20 | # Enable Rack::Cache to put a simple HTTP cache in front of your application 21 | # Add `rack-cache` to your Gemfile before enabling this. 22 | # For large-scale production use, consider using a caching reverse proxy like 23 | # NGINX, varnish or squid. 24 | # config.action_dispatch.rack_cache = true 25 | 26 | # Disable serving static files from the `/public` folder by default since 27 | # Apache or NGINX already handles this. 28 | config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present? 29 | 30 | # Compress JavaScripts and CSS. 31 | config.assets.js_compressor = :uglifier 32 | # config.assets.css_compressor = :sass 33 | 34 | # Do not fallback to assets pipeline if a precompiled asset is missed. 35 | config.assets.compile = false 36 | 37 | # Asset digests allow you to set far-future HTTP expiration dates on all assets, 38 | # yet still be able to expire them through the digest params. 39 | config.assets.digest = true 40 | 41 | # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb 42 | 43 | # Specifies the header that your server uses for sending files. 44 | # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache 45 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX 46 | 47 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 48 | # config.force_ssl = true 49 | 50 | # Use the lowest log level to ensure availability of diagnostic information 51 | # when problems arise. 52 | config.log_level = :debug 53 | 54 | # Prepend all log lines with the following tags. 55 | # config.log_tags = [ :subdomain, :uuid ] 56 | 57 | # Use a different logger for distributed setups. 58 | # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) 59 | 60 | # Use a different cache store in production. 61 | # config.cache_store = :mem_cache_store 62 | 63 | # Enable serving of images, stylesheets, and JavaScripts from an asset server. 64 | # config.action_controller.asset_host = 'http://assets.example.com' 65 | 66 | # Ignore bad email addresses and do not raise email delivery errors. 67 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. 68 | 69 | # ActionMailer Config 70 | config.action_mailer.default_url_options = { :host => 'bpm.j123.ru' } 71 | config.action_mailer.delivery_method = :sendmail 72 | config.action_mailer.perform_deliveries = true 73 | config.action_mailer.raise_delivery_errors = false 74 | config.action_mailer.default :charset => "utf-8" 75 | config.action_mailer.sendmail_settings = { :arguments => "-i" } 76 | 77 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 78 | # the I18n.default_locale when a translation cannot be found). 79 | config.i18n.fallbacks = true 80 | 81 | # Send deprecation notices to registered listeners. 82 | config.active_support.deprecation = :notify 83 | 84 | # Use default logging formatter so that PID and timestamp are not suppressed. 85 | config.log_formatter = ::Logger::Formatter.new 86 | 87 | # Do not dump schema after migrations. 88 | config.active_record.dump_schema_after_migration = false 89 | end 90 | --------------------------------------------------------------------------------