Compare commits

...

16 Commits

Author SHA1 Message Date
Arthur Poulet
193ad1bd44 fix Client#last_view 2016-02-01 02:37:12 +01:00
Arthur Poulet
fec6c7d204 comments are descriptionized 2016-02-01 02:27:43 +01:00
Arthur Poulet
1c5c5b1cc7 rmeove ticket header from ticket form 2016-02-01 02:07:32 +01:00
Arthur Poulet
65f103b22c Merge branch '23-ticket-simples' 2016-01-31 12:03:41 +01:00
Arthur Poulet
51fbef582f finish ticket thread
- use comments instead of a slave tickets
- fix security issues
2016-01-31 12:01:47 +01:00
Arthur Poulet
a769142d2f update tickets
following #13

- tickets have no more master
- tickets are commentables
2016-01-31 02:22:11 +01:00
Arthur Poulet
6dd89038d3 add autompletion for bill
close #21
2016-01-30 23:06:48 +01:00
Arthur Poulet
d04a47541f add autocompletion on contact and client id
- autocompletion to find a main contact for client
- same thing to find a client when create/edit a contact
2016-01-30 23:01:57 +01:00
Arthur Poulet
3f008c6c14 fix buggy commit 2016-01-30 22:17:01 +01:00
Arthur Poulet
464f2e5d5d fix for older thant ruby 2.2 version 2016-01-30 21:57:44 +01:00
Arthur Poulet
12c6dbd0a3 fix typo 2015-08-31 16:43:25 +02:00
Arthur Poulet
a4697dc143 update README 2015-08-09 01:13:15 +02:00
Arthur Poulet
78942c3589 fix commentable request
close #34
2015-08-09 01:12:52 +02:00
Arthur Poulet
9f4abcb06d update gems 2015-08-09 01:00:52 +02:00
Arthur Poulet
0af4b6fb46 Merge branch '32-remove-comment'
close #32
open #33
2015-08-05 02:16:40 +02:00
Arthur Poulet
a23b58df49 update session_store file 2015-08-04 11:57:18 +02:00
34 changed files with 251 additions and 322 deletions

29
Gemfile
View File

@ -1,6 +1,5 @@
source 'https://rubygems.org' source 'https://rubygems.org'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.2.1' gem 'rails', '4.2.1'
# Use sqlite3 as the database for Active Record # Use sqlite3 as the database for Active Record
@ -51,21 +50,25 @@ end
# Web Server # Web Server
gem 'puma' gem 'puma'
# Database
gem 'pg'
# Upload
gem 'carrierwave'
# Environnement .env # Environnement .env
gem 'dotenv-rails' gem 'dotenv-rails'
# Database
gem 'pg'
# Users # Users
gem 'devise' gem 'devise'
# Pagination # Upload
gem 'will_paginate' gem 'carrierwave'
# Bootstrap
gem "twitter-bootstrap-rails"
# Bootstrap for pagination
gem 'bootstrap-will_paginate'
# HTML Templating
gem 'slim-rails'
# Commentable items # Commentable items
gem 'acts_as_commentable' gem 'acts_as_commentable'
# HTML Templating
gem 'slim-rails'
# Bootstrap
gem "twitter-bootstrap-rails"
# Pagination
gem 'will_paginate'
# Bootstrap for pagination
gem 'bootstrap-will_paginate'
# Autocomplete for ids
gem 'rails-jquery-autocomplete'

View File

@ -37,7 +37,7 @@ GEM
thread_safe (~> 0.3, >= 0.3.4) thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1) tzinfo (~> 1.1)
acts_as_commentable (4.0.2) acts_as_commentable (4.0.2)
arel (6.0.2) arel (6.0.3)
bcrypt (3.1.10) bcrypt (3.1.10)
binding_of_caller (0.7.2) binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1) debug_inspector (>= 0.0.1)
@ -75,7 +75,7 @@ GEM
railties (~> 4.0) railties (~> 4.0)
erubis (2.7.0) erubis (2.7.0)
execjs (2.5.2) execjs (2.5.2)
globalid (0.3.5) globalid (0.3.6)
activesupport (>= 4.1.0) activesupport (>= 4.1.0)
i18n (0.7.0) i18n (0.7.0)
jbuilder (2.3.1) jbuilder (2.3.1)
@ -95,7 +95,7 @@ GEM
method_source (0.8.2) method_source (0.8.2)
mime-types (2.6.1) mime-types (2.6.1)
mini_portile (0.6.2) mini_portile (0.6.2)
minitest (5.7.0) minitest (5.8.0)
multi_json (1.11.2) multi_json (1.11.2)
nokogiri (1.6.6.2) nokogiri (1.6.6.2)
mini_portile (~> 0.6.0) mini_portile (~> 0.6.0)
@ -105,7 +105,7 @@ GEM
coderay (~> 1.1.0) coderay (~> 1.1.0)
method_source (~> 0.8.1) method_source (~> 0.8.1)
slop (~> 3.4) slop (~> 3.4)
puma (2.12.1) puma (2.12.3)
rack (1.6.4) rack (1.6.4)
rack-test (0.6.3) rack-test (0.6.3)
rack (>= 1.0) rack (>= 1.0)
@ -126,13 +126,15 @@ GEM
activesupport (>= 4.2.0.beta, < 5.0) activesupport (>= 4.2.0.beta, < 5.0)
nokogiri (~> 1.6.0) nokogiri (~> 1.6.0)
rails-deprecated_sanitizer (>= 1.0.1) rails-deprecated_sanitizer (>= 1.0.1)
rails-erd (1.4.1) rails-erd (1.4.2)
activerecord (>= 3.2) activerecord (>= 3.2)
activesupport (>= 3.2) activesupport (>= 3.2)
choice (~> 0.2.0) choice (~> 0.2.0)
ruby-graphviz (~> 1.2) ruby-graphviz (~> 1.2)
rails-html-sanitizer (1.0.2) rails-html-sanitizer (1.0.2)
loofah (~> 2.0) loofah (~> 2.0)
rails-jquery-autocomplete (1.0.3)
rails (>= 3.2)
railties (4.2.1) railties (4.2.1)
actionpack (= 4.2.1) actionpack (= 4.2.1)
activesupport (= 4.2.1) activesupport (= 4.2.1)
@ -214,6 +216,7 @@ DEPENDENCIES
puma puma
rails (= 4.2.1) rails (= 4.2.1)
rails-erd rails-erd
rails-jquery-autocomplete
sass-rails (~> 5.0) sass-rails (~> 5.0)
sdoc (~> 0.4.0) sdoc (~> 0.4.0)
slim-rails slim-rails
@ -225,4 +228,4 @@ DEPENDENCIES
will_paginate will_paginate
BUNDLED WITH BUNDLED WITH
1.10.5 1.11.2

View File

@ -16,8 +16,6 @@ I want a simple application, that I __understand__, and that I __need__. By __si
- A pluggable application, with many __REST API__. Because tasks and reports are usefull. - A pluggable application, with many __REST API__. Because tasks and reports are usefull.
- Generic items. I prefere __ONE kind of Bills + Tags__ than __4 ou 5 kinds of Bills__ (for example). - Generic items. I prefere __ONE kind of Bills + Tags__ than __4 ou 5 kinds of Bills__ (for example).
I would like money, contributions, critics, etc.
<img alt="Tickets Desktop view" src="http://i.imgur.com/e004zBZ.png" width="500" /> <img alt="Tickets Desktop view" src="http://i.imgur.com/e004zBZ.png" width="500" />
@ -31,18 +29,19 @@ I would like money, contributions, critics, etc.
2. [Contributions](#2-contributions) 2. [Contributions](#2-contributions)
1. [Contributors](#21-contributors) 1. [Contributors](#21-contributors)
2. [How to contribute](#22-how-to-contribute-) 2. [How to contribute](#22-how-to-contribute-)
3. [License](#23-license)
3. [Architecture](#3-architecture)
1. [Modelisation](#31-modelisation)
# 1. Installation # 1. Installation
## 1.1. Requirements ## 1.1. Requirements
- Ruby 2.0 or greater. - Ruby 2.0 or greater.
- Postgresql server 9 or greater running with creditentials. - Postgresql server 9 or greater running with creditentials.
## 1.2. Initialization ## 1.2. Initialization
Start by pasting this script in your shell: Start by pasting this script in your shell:
```bash ```bash
cd MorningPeak/ cd MorningPeak/
@ -56,7 +55,6 @@ rake db:seed # will generate default data. Not on production ;)
``` ```
## 1.3. Configuration ## 1.3. Configuration
- You can create a file ``.env`` to save your locals cvars without pollute your global env. - You can create a file ``.env`` to save your locals cvars without pollute your global env.
- You can also create ``.env.production`` etc. for environement specifics cvars - You can also create ``.env.production`` etc. for environement specifics cvars
- A ``.env`` file looks like: - A ``.env`` file looks like:
@ -70,7 +68,6 @@ LOCALE: fr
- COMPANY - COMPANY
## 1.4. First start ## 1.4. First start
When you done with the configuration of the database (editing ``config/database.yml``), When you done with the configuration of the database (editing ``config/database.yml``),
you can run the server by the following command : you can run the server by the following command :
``` ```
@ -99,7 +96,6 @@ Checkout for [rails minidoc](RailsMinidoc.md) for a resume of rails.
<img alt="Look at this cute face" src="https://pbs.twimg.com/media/CJ_ErJ2W8AAdev3.jpg" width="200" height="150" /> <img alt="Look at this cute face" src="https://pbs.twimg.com/media/CJ_ErJ2W8AAdev3.jpg" width="200" height="150" />
## 2.2. How to contribute ? ## 2.2. How to contribute ?
You can contribute to this project by Merge Request on the gitlab repository [here](https://gitlab.com/poulet_a/MorningPeak). You can contribute to this project by Merge Request on the gitlab repository [here](https://gitlab.com/poulet_a/MorningPeak).
The best pratices are to create short commits, and short Merge Requests. Respect the git commit nomage convention as possible with: The best pratices are to create short commits, and short Merge Requests. Respect the git commit nomage convention as possible with:
@ -110,3 +106,28 @@ The best pratices are to create short commits, and short Merge Requests. Respect
We accept any kind of work : translations, bug fix, additionnal features, optimizations, documentation, etc. We accept any kind of work : translations, bug fix, additionnal features, optimizations, documentation, etc.
Don't be afraid ! Don't be afraid !
## 2.3. License
see the license in the ``License`` file.
It is under:
```text
GNU GENERAL PUBLIC LICENSE
```
# 3. Architecture
## 3.1 Modelisation
### Creation and belongs
- User has a Client (which is created when the user is created)
- Client has many Contacts and Bills
- User/Admin has many Tickets and Comments
### Permissions
- Admin can Comment, Read, Edit, Delete, and Create everything
- User can open Ticket, Anwser and Close them.
- User can Read every Bills wich is associated to him
- User can not read his client informations (like notes, ...)

View File

@ -14,4 +14,6 @@
//= require jquery_ujs //= require jquery_ujs
//= require jquery-ui //= require jquery-ui
//= require twitter/bootstrap //= require twitter/bootstrap
//= require jquery-ui/autocomplete
//= require autocomplete-rails
//= require_tree . //= require_tree .

View File

@ -3,6 +3,9 @@ commentableLoadComments = (base_url) ->
$("#comments").html(e) $("#comments").html(e)
$(document).ready -> $(document).ready ->
commentableLoadComments(window.location.href) url = window.location.pathname
commentableLoadComments(url)
$(document).on "ajax:success", "#new_comment", (e, data, status, xhr) -> $(document).on "ajax:success", "#new_comment", (e, data, status, xhr) ->
commentableLoadComments(window.location.href) commentableLoadComments(url)
$(document).on "ajax:complete", ".remove-comment", (e, data, status, xhr) ->
commentableLoadComments(url)

View File

@ -1,6 +1,8 @@
class BillsController < ApplicationController class BillsController < ApplicationController
include CommentableForm include CommentableForm
autocomplete :client, :name
before_action :set_bill, only: [:show, :edit, :update, :destroy] before_action :set_bill, only: [:show, :edit, :update, :destroy]
before_action :authenticate_admin! before_action :authenticate_admin!

View File

@ -1,4 +1,6 @@
class ClientTicketsController < ApplicationController class ClientTicketsController < ApplicationController
include CommentableForm
before_action :set_ticket, only: [:show, :edit, :update, :destroy] before_action :set_ticket, only: [:show, :edit, :update, :destroy]
before_action :set_ticket_custom_route, only: [:close, :open, :respond] before_action :set_ticket_custom_route, only: [:close, :open, :respond]
before_action :looks_ticket, only: [:show, :edit, :update, :close, :open] before_action :looks_ticket, only: [:show, :edit, :update, :close, :open]
@ -7,13 +9,13 @@ class ClientTicketsController < ApplicationController
# GET /tickets # GET /tickets
# GET /tickets.json # GET /tickets.json
def index def index
@tickets = current_user.tickets.heads.order('state DESC') @tickets = current_user.tickets.order('state DESC')
end end
def close def close
respond_to do |format| respond_to do |format|
if @ticket.close if @ticket.close
@ticket.update(admin_view_at: Time.now) @ticket.update(admin_view_at: Time.now) # add comment ?
format.html { redirect_to client_ticket_url(@ticket), notice: 'Ticket was successfully closed.' } format.html { redirect_to client_ticket_url(@ticket), notice: 'Ticket was successfully closed.' }
format.json { render :show, status: :ok, location: client_tickets_url(@ticket) } format.json { render :show, status: :ok, location: client_tickets_url(@ticket) }
else else
@ -26,7 +28,7 @@ class ClientTicketsController < ApplicationController
def open def open
respond_to do |format| respond_to do |format|
if @ticket.open if @ticket.open
@ticket.update(admin_view_at: nil) @ticket.update(admin_view_at: nil) # add comment ?
format.html { redirect_to client_ticket_url(@ticket), notice: 'Ticket was successfully reopened.' } format.html { redirect_to client_ticket_url(@ticket), notice: 'Ticket was successfully reopened.' }
format.json { render :show, status: :ok, location: client_tickets_url(@ticket) } format.json { render :show, status: :ok, location: client_tickets_url(@ticket) }
else else
@ -36,25 +38,10 @@ class ClientTicketsController < ApplicationController
end end
end end
def respond
session[:user_ticket_respond_parent_id] = @ticket.id
@head = @ticket.head
@ticket = Ticket.new(ticket_id: @head.id,
creator: current_user,
title: @ticket.title)
if @ticket.close? or @head.close?
respond_to do |format|
format.html { redirect_to client_ticket_url(@head), alert: 'The ticket is closed' }
format.json { render json: {ticket: 'The ticket is closed'}, status: :unprocessable_entity }
end
else
render :new
end
end
# GET /tickets/1 # GET /tickets/1
# GET /tickets/1.json # GET /tickets/1.json
def show def show
prepare_comment_for @ticket
end end
# GET /tickets/new # GET /tickets/new
@ -70,15 +57,10 @@ class ClientTicketsController < ApplicationController
# POST /tickets.json # POST /tickets.json
def create def create
@ticket = Ticket.new(ticket_params) @ticket = Ticket.new(ticket_params)
if session[:user_ticket_respond_parent_id]
@head = Ticket.find(session[:user_ticket_respond_parent_id]).head
@ticket.ticket_id = @head.id
end
@ticket.creator = current_user @ticket.creator = current_user
respond_to do |format| respond_to do |format|
if @ticket.save if @ticket.save
@ticket.close_head if @ticket.close?
format.html { redirect_to client_ticket_url(@ticket), notice: 'Ticket was successfully created.' } format.html { redirect_to client_ticket_url(@ticket), notice: 'Ticket was successfully created.' }
format.json { render :show, status: :created, location: client_tickets_url(@ticket) } format.json { render :show, status: :created, location: client_tickets_url(@ticket) }
else else
@ -93,7 +75,6 @@ class ClientTicketsController < ApplicationController
def update def update
respond_to do |format| respond_to do |format|
if @ticket.update(ticket_params) if @ticket.update(ticket_params)
@ticket.close_head if @ticket.close?
format.html { redirect_to @ticket, notice: 'Ticket was successfully updated.' } format.html { redirect_to @ticket, notice: 'Ticket was successfully updated.' }
format.json { render :show, status: :ok, location: client_tickets_url(@ticket) } format.json { render :show, status: :ok, location: client_tickets_url(@ticket) }
else else
@ -116,11 +97,11 @@ class ClientTicketsController < ApplicationController
private private
# Use callbacks to share common setup or constraints between actions. # Use callbacks to share common setup or constraints between actions.
def set_ticket def set_ticket
@ticket = Ticket.find(params[:id]) @ticket = Ticket.find_by(id: params[:id], creator: current_user)
@ticket = nil if not @ticket.creator == current_user and not @ticket.head.creator == current_user
@ticket @ticket
end end
# TODO: remove
def set_ticket_custom_route def set_ticket_custom_route
params[:id] = params[:client_ticket_id] params[:id] = params[:client_ticket_id]
set_ticket set_ticket
@ -132,12 +113,7 @@ class ClientTicketsController < ApplicationController
end end
def looks_ticket def looks_ticket
if @ticket.head.head_creator_view_at.nil? @ticket.set_view_by('User')
@ticket.head.update(head_creator_view_at: Time.now)
end
Ticket.where(creator: current_user, head_creator_view_at: nil, ticket: @ticket.head).each do |t|
t.update(head_creator_view_at: Time.now)
end
end end
end end

View File

@ -1,6 +1,8 @@
class ClientsController < ApplicationController class ClientsController < ApplicationController
include CommentableForm include CommentableForm
autocomplete :contact, :name
before_action :authenticate_admin! before_action :authenticate_admin!
before_action :set_client, only: [:show, :edit, :update, :destroy] before_action :set_client, only: [:show, :edit, :update, :destroy]

View File

@ -1,43 +1,53 @@
class CommentsController < ApplicationController class CommentsController < ApplicationController
before_action :authenticate_admin!
before_action :set_comment, only: [:show, :edit, :update, :destroy] before_action :set_comment, only: [:show, :edit, :update, :destroy]
before_action :set_client, only: [:index, :about, :new] before_action :set_commentable, only: [:index, :about, :show, :create]
before_action :set_contact, only: [:index, :about, :new] before_action :set_commentable_client, only: [:about_client, :show, :create]
before_action :set_bill, only: [:index, :about, :new]
# GET /comments # GET /comments
# GET /comments.json # GET /comments.json
def index def index
@comments = Comment.all @comments = Comment.where(commentable: @commentable) if @commentable
@comments = @comments.where(commentable: @commentable) if @commentable @comments ||= Comment.where('0=1')
end end
def about def about
index() index()
@comment = Comment.new @comment = Comment.new
@comment.commentable = @commentable @comment.commentable = @commentable
render :about, layout: false render :about, layout: false
end end
def about_client
index()
@comment = Comment.new
@comment.commentable = @commentable
render :about_client, layout: false
end
# GET /comments/1 # GET /comments/1
# GET /comments/1.json # GET /comments/1.json
def show def show
binding.pry
render status: :forbidden unless admin_signed_in? or (user_signed_in? and @comment.commentable.is_a? Ticket and @comment.commentable.creator == current_user)
end end
# GET /comments/new # GET /comments/new
def new def new
@comment = Comment.new @comment = Comment.new
@comment.commentable = @commentable @comment.commentable = @commentable
render status: :forbidden unless admin_signed_in? or (user_signed_in? and @comment.commentable.is_a? Ticket and @comment.commentable.creator == current_user)
end end
# GET /comments/1/edit # GET /comments/1/edit
def edit def edit
render status: :forbidden unless admin_signed_in? or (user_signed_in? and @comment.commentable.is_a? Ticket and @comment.commentable.creator == current_user)
end end
# POST /comments # POST /comments
# POST /comments.json # POST /comments.json
def create def create
@comment = Comment.new(comment_params) @comment = Comment.new(comment_params)
@comment.creator = current_admin @comment.creator = (current_admin || current_user)
render status: :forbidden unless admin_signed_in? or (user_signed_in? and @comment.commentable.is_a? Ticket and @comment.commentable.creator == current_user)
respond_to do |format| respond_to do |format|
if @comment.save if @comment.save
@ -53,6 +63,7 @@ class CommentsController < ApplicationController
# PATCH/PUT /comments/1 # PATCH/PUT /comments/1
# PATCH/PUT /comments/1.json # PATCH/PUT /comments/1.json
def update def update
render status: :forbidden unless admin_signed_in?
respond_to do |format| respond_to do |format|
if @comment.update(comment_params) if @comment.update(comment_params)
format.html { redirect_to @comment, notice: 'Comment was successfully updated.' } format.html { redirect_to @comment, notice: 'Comment was successfully updated.' }
@ -67,6 +78,7 @@ class CommentsController < ApplicationController
# DELETE /comments/1 # DELETE /comments/1
# DELETE /comments/1.json # DELETE /comments/1.json
def destroy def destroy
render status: :forbidden unless admin_signed_in?
@comment.destroy @comment.destroy
respond_to do |format| respond_to do |format|
format.html { redirect_to comments_url, notice: 'Comment was successfully destroyed.' } format.html { redirect_to comments_url, notice: 'Comment was successfully destroyed.' }
@ -87,14 +99,19 @@ class CommentsController < ApplicationController
:role) :role)
end end
def set_client def set_commentable
return unless admin_signed_in?
@commentable ||= Client.find_by_id(params[:client_id]) @commentable ||= Client.find_by_id(params[:client_id])
end
def set_contact
@commentable ||= Contact.find_by_id(params[:contact_id]) @commentable ||= Contact.find_by_id(params[:contact_id])
end
def set_bill
@commentable ||= Bill.find_by_id(params[:bill_id]) @commentable ||= Bill.find_by_id(params[:bill_id])
@commentable ||= Ticket.find_by_id(params[:ticket_id])
@commentable_by = 'Admin'
end
def set_commentable_client
return unless user_signed_in?
if @commentable.nil?
@commentable ||= Ticket.find_by(id: params[:client_ticket_id], creator: current_user)
end
end end
end end

View File

@ -1,6 +1,8 @@
class ContactsController < ApplicationController class ContactsController < ApplicationController
include CommentableForm include CommentableForm
autocomplete :client, :name
before_action :set_contact, only: [:show, :edit, :update, :destroy, :view] before_action :set_contact, only: [:show, :edit, :update, :destroy, :view]
before_action :authenticate_admin! before_action :authenticate_admin!

View File

@ -8,8 +8,8 @@ class HomeController < ApplicationController
@next_bills = current_user.bills.next.count @next_bills = current_user.bills.next.count
@old_bills = current_user.bills.old.count @old_bills = current_user.bills.old.count
@bills_count = current_user.bills.count @bills_count = current_user.bills.count
@ticket_closed = current_user.tickets.heads.close.count @ticket_closed = current_user.tickets.close.count
@ticket_opened = current_user.tickets.heads.open.count @ticket_opened = current_user.tickets.open.count
@ticket_waiting = current_user.tickets_unview.count @ticket_waiting = current_user.tickets_unview.count
end end
@ -22,8 +22,8 @@ class HomeController < ApplicationController
@next_bills = Bill.next.count @next_bills = Bill.next.count
@old_bills = Bill.old.count @old_bills = Bill.old.count
@bills_count = Bill.count @bills_count = Bill.count
@ticket_closed = Ticket.heads.close.count @ticket_closed = Ticket.close.count
@ticket_opened = Ticket.heads.open.count @ticket_opened = Ticket.open.count
@ticket_waiting = current_admin.tickets_unview.count @ticket_waiting = current_admin.tickets_unview.count
end end

View File

@ -1,19 +1,21 @@
class TicketsController < ApplicationController class TicketsController < ApplicationController
include CommentableForm
before_action :set_ticket, only: [:show, :edit, :update, :destroy] before_action :set_ticket, only: [:show, :edit, :update, :destroy]
before_action :set_ticket_custom_route, only: [:close, :open, :respond] before_action :set_ticket_custom_route, only: [:close, :open]
before_action :looks_ticket, only: [:show, :edit, :update, :close, :open] before_action :looks_ticket, only: [:show, :edit, :update, :close, :open]
before_action :authenticate_admin! before_action :authenticate_admin!
# GET /tickets # GET /tickets
# GET /tickets.json # GET /tickets.json
def index def index
@tickets = Ticket.heads.order('state DESC') @tickets = Ticket.order('state DESC')
end end
def close def close
respond_to do |format| respond_to do |format|
if @ticket.close if @ticket.close
@ticket.update(admin_view_at: Time.now) @ticket.update(admin_view_at: Time.now) # add comment ?
format.html { redirect_to ticket_url(@ticket), notice: 'Ticket was successfully closed.' } format.html { redirect_to ticket_url(@ticket), notice: 'Ticket was successfully closed.' }
format.json { render :show, status: :ok, location: @ticket } format.json { render :show, status: :ok, location: @ticket }
else else
@ -26,7 +28,7 @@ class TicketsController < ApplicationController
def open def open
respond_to do |format| respond_to do |format|
if @ticket.open if @ticket.open
@ticket.update(head_creator_view_at: nil) @ticket.update(creator_view_at: nil) # add comment ?
format.html { redirect_to ticket_url(@ticket), notice: 'Ticket was successfully reopened.' } format.html { redirect_to ticket_url(@ticket), notice: 'Ticket was successfully reopened.' }
format.json { render :show, status: :ok, location: @ticket } format.json { render :show, status: :ok, location: @ticket }
else else
@ -36,24 +38,10 @@ class TicketsController < ApplicationController
end end
end end
def respond
@head = @ticket.head
@ticket = Ticket.new(ticket_id: @head.id,
creator: current_admin,
title: @ticket.title)
if @ticket.close? or @head.close?
respond_to do |format|
format.html { redirect_to ticket_url(@head), alert: 'the ticket is closed' }
format.json { render json: {ticket: 'the ticket is closed'}, status: :unprocessable_entity }
end
else
render :new
end
end
# GET /tickets/1 # GET /tickets/1
# GET /tickets/1.json # GET /tickets/1.json
def show def show
prepare_comment_for @ticket
end end
# GET /tickets/new # GET /tickets/new
@ -88,7 +76,6 @@ class TicketsController < ApplicationController
def update def update
respond_to do |format| respond_to do |format|
if @ticket.update(ticket_params) if @ticket.update(ticket_params)
@ticket.close_head if @ticket.close?
format.html { redirect_to @ticket, notice: 'Ticket was successfully updated.' } format.html { redirect_to @ticket, notice: 'Ticket was successfully updated.' }
format.json { render :show, status: :ok, location: @ticket } format.json { render :show, status: :ok, location: @ticket }
else else
@ -120,16 +107,11 @@ class TicketsController < ApplicationController
# Never trust parameters from the scary internet, only allow the white list through. # Never trust parameters from the scary internet, only allow the white list through.
def ticket_params def ticket_params
params.require(:ticket).permit(:ticket_id, :title, :description, :state) params.require(:ticket).permit(:title, :description, :state)
end end
def looks_ticket def looks_ticket
if @ticket.head.admin_view_at.nil? @ticket.set_view_by('Admin')
@ticket.head.update(admin_view_at: Time.now)
end
Ticket.where(creator: current_admin, admin_view_at: nil, ticket: @ticket.head).each do |t|
t.update(admin_view_at: Time.now)
end
end end
end end

View File

@ -12,7 +12,7 @@ class Admin < ActiveRecord::Base
has_many :comments, as: :creator has_many :comments, as: :creator
def tickets_unview def tickets_unview
Ticket.all.heads.where(admin_view_at: nil) Ticket.all.where(admin_view_at: nil)
end end
end end

View File

@ -1,5 +1,6 @@
class Client < ActiveRecord::Base class Client < ActiveRecord::Base
acts_as_commentable acts_as_commentable
has_many :contacts has_many :contacts
has_many :bills has_many :bills
has_many :tickets, through: :user has_many :tickets, through: :user
@ -9,7 +10,7 @@ class Client < ActiveRecord::Base
delegate :name, to: :contact, allow_nil: true, prefix: true delegate :name, to: :contact, allow_nil: true, prefix: true
def last_contact def last_contact
contacts.pluck(:view_at).max || "never" contacts.where('view_at IS NOT NULL').pluck(:view_at).max || "never"
end end
def bills_retard def bills_retard

View File

@ -3,7 +3,7 @@ class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true belongs_to :commentable, :polymorphic => true
default_scope -> { order('created_at ASC') } default_scope -> { order('created_at DESC') }
# NOTE: install the acts_as_votable plugin if you # NOTE: install the acts_as_votable plugin if you
# want user to vote on the quality of comments. # want user to vote on the quality of comments.
@ -21,4 +21,11 @@ class Comment < ActiveRecord::Base
end end
end end
after_create :update_view_date_for_ticket
def update_view_date_for_ticket
if commentable.is_a? Ticket
commentable.updated_by(creator.class.to_s)
end
end
end end

View File

@ -1,5 +1,7 @@
# coding: utf-8 # coding: utf-8
class Ticket < ActiveRecord::Base class Ticket < ActiveRecord::Base
acts_as_commentable
# WARNING ! IT REVERSE LAST / FIRST # WARNING ! IT REVERSE LAST / FIRST
default_scope { order('created_at DESC') } default_scope { order('created_at DESC') }
@ -16,12 +18,8 @@ class Ticket < ActiveRecord::Base
belongs_to :creator, polymorphic: true belongs_to :creator, polymorphic: true
delegate :name, to: :creator, prefix: true delegate :name, to: :creator, prefix: true
belongs_to :ticket scope :open, -> { where(state: OPEN) }
has_many :tickets scope :close, -> { where(state: CLOSE) }
scope :heads, -> { where(ticket_id: nil) }
scope :open, -> { heads.where(state: OPEN) }
scope :close, -> { heads.where(state: CLOSE) }
before_save :check_creator before_save :check_creator
def check_creator def check_creator
@ -30,39 +28,40 @@ class Ticket < ActiveRecord::Base
raise ActiveRecord::RecordInvalid.new(self) raise ActiveRecord::RecordInvalid.new(self)
end end
after_create :looks_views after_create :set_view_init
def looks_views def set_view_init
set_view_by(creator_type)
end
def set_view_by(viewer_type)
if creator_type == 'Admin' if creator_type == 'Admin'
# Entre admin pas de soucis if viewer_type == 'Admin'
if head.creator_type == 'Admin' update(admin_view_at: Time.now, creator_view_at: Time.now)
update(admin_view_at: Time.now, head_creator_view_at: Time.now)
# Réponse à un client, mise a jour pour notification
else
update(admin_view_at: Time.now, head_creator_view_at: nil)
head.update(admin_view_at: Time.now, head_creator_view_at: nil)
end end
else elsif creator_type == 'User'
# Reponse client, mise a jour pour notification if viewer_type == 'User'
if head? update(creator_view_at: Time.now)
update(admin_view_at: nil, head_creator_view_at: Time.now) elsif viewer_type == 'Admin'
else update(admin_view_at: Time.now)
update(admin_view_at: nil, head_creator_view_at: Time.now)
head.update(admin_view_at: nil, head_creator_view_at: Time.now)
end end
end end
end end
def last_response def set_unview_by(viewer_type)
head.tickets.last if creator_type == 'Admin'
return # ... ?
elsif creator_type == 'User'
if viewer_type == 'User'
update(admin_view_at: nil)
elsif viewer_type == 'Admin'
update(creator_view_at: nil)
end
end
end end
def head def updated_by(viewer_type)
return self if head? set_view_by(viewer_type)
return ticket.head set_unview_by(viewer_type)
end
def head?
ticket.nil?
end end
def close def close
@ -70,15 +69,7 @@ class Ticket < ActiveRecord::Base
errors[:base] << "Already close" errors[:base] << "Already close"
return false return false
end end
head.update(state: Ticket::CLOSE) && update(state: Ticket::CLOSE) update(state: Ticket::CLOSE)
end
def close_head
if head.close?
errors[:base] << "Already close"
return false
end
head.update(state: Ticket::CLOSE)
end end
def open def open
@ -86,7 +77,7 @@ class Ticket < ActiveRecord::Base
errors[:base] << "Already open" errors[:base] << "Already open"
return false return false
end end
head.update(state: Ticket::OPEN) && update(state: Ticket::OPEN) update(state: Ticket::OPEN)
end end
def open? def open?
@ -98,11 +89,7 @@ class Ticket < ActiveRecord::Base
end end
def short_description def short_description
if description.size > 100 description.to_s.first(100)
description[0..97] + "..."
else
description
end
end end
end end

View File

@ -16,11 +16,13 @@ class User < ActiveRecord::Base
after_create :create_client after_create :create_client
def create_client def create_client
update(client: Client.create(name: email.gsub(/@.+/, ''))) if self.client_id.nil?
update_attributes(client: Client.create(name: email.tr('@.-_', ' ')))
end
end end
def tickets_unview def tickets_unview
tickets.heads.where(head_creator_view_at: nil) tickets.where(creator_view_at: nil)
end end
end end

View File

@ -9,8 +9,9 @@
.form-horizontal .form-horizontal
.form-group .form-group
.field .field
= f.autocomplete_field :client, autocomplete_client_name_bills_path, :id_element => '#bill_client_id', class: "form-control", placeholder: "Client Name"
= f.label :client_id, class: "sr-only" = f.label :client_id, class: "sr-only"
= f.text_field :client_id, class: "form-control", placeholder: "#{t('.client_id')}" = f.text_field :client_id, class: "form-control sr-only", placeholder: "#{t('.client_id')}"
.form-group .form-group
.field .field
= f.label :title, class: "sr-only" = f.label :title, class: "sr-only"

View File

@ -4,7 +4,6 @@ table.table.table-condensed
thead thead
tr tr
th ID th ID
th = t ".creator"
th = t ".title" th = t ".title"
th = t ".description" th = t ".description"
th = t ".state" th = t ".state"
@ -13,25 +12,21 @@ table.table.table-condensed
th th
th th
th th
th
tbody tbody
- @tickets.each do |ticket| - @tickets.each do |ticket|
tr class="#{ticket.head_creator_view_at.nil? ? 'bg-warning' : ''}" tr class="#{ticket.creator_view_at.nil? ? 'bg-warning' : ''}"
td = link_to("##{ticket.id}", client_ticket_path(ticket)) td = link_to("##{ticket.id}", client_ticket_path(ticket))
td = link_to_creator(ticket)
td = link_to ticket.title, client_ticket_path(ticket) td = link_to ticket.title, client_ticket_path(ticket)
td = ticket.tickets.empty? ? ticket.description : ticket.tickets.first.description td = ticket.short_description
- if ticket.state == Ticket::CLOSE - if ticket.state == Ticket::CLOSE
td.bg-danger = t ".states.close" td.bg-danger = t ".states.close"
- else - else
td.bg-success = t ".states.open" td.bg-success = t ".states.open"
td = ticket.updated_at.to_s(:long) td = ticket.updated_at.to_s(:long)
td = ticket.last_response ? distance_of_time_in_words_to_now(ticket.last_response.updated_at) : "never" td = ticket.comments.empty? ? "never" : distance_of_time_in_words_to_now(ticket.comments.first.updated_at)
td = link_to (t "show"), ticket td = link_to (t "show"), ticket
td = link_to (t "edit"), edit_client_ticket_path(ticket) td = link_to (t "edit"), edit_client_ticket_path(ticket)
/ td = link_to 'Destroy', ticket, data: {:confirm => 'Are you sure?'}, :method => :delete
td = link_to (t "respond"), client_ticket_respond_path(ticket) if ticket.open?
- if ticket.open? - if ticket.open?
td = link_to (t "close"), client_ticket_close_path(ticket), data: {:confirm => 'Are you sure?'}, :method => :patch td = link_to (t "close"), client_ticket_close_path(ticket), data: {:confirm => 'Are you sure?'}, :method => :patch
- elsif ticket.close? - elsif ticket.close?

View File

@ -1,18 +1,18 @@
h1.page-header = "Ticket: #{@ticket.head.title}" h1.page-header = "Ticket: #{@ticket.title}"
p p
strong strong
| Id: # | Id: #
= @ticket.id = @ticket.id
p p
strong = t ".respond_to" strong = t ".title"
|:  |: 
= link_to @ticket.head.title, client_ticket_path(@ticket.head) = link_to @ticket.title, client_ticket_path(@ticket)
p p
strong = t ".state" strong = t ".state"
|:  |: 
- if @ticket.head.state == Ticket::CLOSE - if @ticket.state == Ticket::CLOSE
td.bg-danger = t ".states.close" td.bg-danger = t ".states.close"
- else - else
td.bg-success = t ".states.open" td.bg-success = t ".states.open"
@ -31,38 +31,14 @@ p
.container-fluid.ticket-description .container-fluid.ticket-description
= descriptionize @ticket.description = descriptionize @ticket.description
- if not @ticket.tickets.empty? == render partial: "/comments/thread", locals: {commentable: @ticket, type: 'user'}
table.table.table-condensed
thead
tr
th = t ".creator"
th = t ".title"
th = t ".description"
th = t ".state"
th = t ".last_update"
th
/ th
tbody
- @ticket.tickets.each do |ticket|
tr
td = link_to_creator(ticket)
td = link_to ticket.title, client_ticket_path(ticket)
td = ticket.short_description
- if ticket.state == Ticket::CLOSE
td.bg-danger = ticket.state
- else
td.bg-success = ticket.state
td = ticket.updated_at.to_s(:long)
td = link_to (t "show"), client_ticket_path(ticket)
td = link_to (t "edit"), edit_client_ticket_path(ticket)
br br
- if @ticket.open? - if @ticket.open?
= link_to (t 'respond'), client_ticket_respond_path(@ticket), class: 'btn btn-sm btn-default'
= link_to (t 'close'), client_ticket_close_path(@ticket), method: :patch, class: 'btn btn-sm btn-success' = link_to (t 'close'), client_ticket_close_path(@ticket), method: :patch, class: 'btn btn-sm btn-success'
- else - else
= link_to (t 'reopen'), client_ticket_open_path(@ticket), method: :patch, class: 'btn btn-sm btn-danger' = link_to (t 'reopen'), client_ticket_open_path(@ticket), method: :patch, class: 'btn btn-sm btn-danger'
= link_to (t 'edit'), edit_client_ticket_path(@ticket), class: 'btn btn-sm btn-default' = link_to (t 'edit'), edit_client_ticket_path(@ticket), class: 'btn btn-sm btn-default'
= link_to (t 'back'), client_tickets_path, class: 'btn btn-sm btn-default' = link_to (t 'back'), client_tickets_path, class: 'btn btn-sm btn-default'

View File

@ -18,7 +18,7 @@
.form-group .form-group
.field .field
= f.label :activity, class: "sr-only" = f.label :activity, class: "sr-only"
= f.text_field :activity, class: "form-control", placeholder: "Acitvity" = f.text_field :activity, class: "form-control", placeholder: "Activity"
.form-group .form-group
.field .field
= f.label :contact_reasons, class: "sr-only" = f.label :contact_reasons, class: "sr-only"
@ -30,6 +30,7 @@
= f.text_field :user_id, class: "form-control", placeholder: "User ID" = f.text_field :user_id, class: "form-control", placeholder: "User ID"
.form-group .form-group
.field .field
= f.autocomplete_field :contact, autocomplete_contact_name_clients_path, :id_element => '#client_contact_id', class: "form-control", placeholder: "Main Contact Name"
= f.label :contact_id, class: "sr-only" = f.label :contact_id, class: "sr-only"
= f.text_field :contact_id, class: "form-control", placeholder: "Main Contact ID" = f.text_field :contact_id, class: "form-control sr-only", placeholder: "Main Contact ID"
.actions = f.submit class: "btn btn-success" .actions = f.submit class: "btn btn-success"

View File

@ -1,13 +1,14 @@
table.table.table-condensed table.table.table-condensed
tr
th Creator
th Title
th Content
th
- commentable.comments.each do |c|
tr tr
th Title td = c.creator_type
th Content td = c.title
th td = descriptionize c.comment
- commentable.comments.each do |c| td
tr = link_to "/comments/#{c.id}.json", remote: true, data: {:confirm => 'Are you sure?'}, method: :delete, class: "close remove-comment", type: "button", "aria-label" => "Close" do
td = c.title span aria-hidden="true" &times;
td = c.comment
td
= link_to c, remote: true, data: {:confirm => 'Are you sure?'}, method: :delete, class: "close remove-comment", type: "button", "aria-label": "Close" do
span aria-hidden="true" &times;

View File

@ -0,0 +1,10 @@
table.table.table-condensed
tr
th Creator
th Title
th Content
- commentable.comments.each do |c|
tr
td = c.creator_type
td = c.title
td = descriptionize c.comment

View File

@ -0,0 +1,4 @@
#comments.container-fluid
h2.page-header Comments
= render partial: "/comments/form"
= render partial: "/comments/about#{type == 'user' ? '_client' : '' }", locals: {commentable: commentable}

View File

@ -1,4 +1 @@
h2 = "Comments" == render partial: 'thread', locals: {commentable: @commentable, type: 'admin'}
== render partial: 'about', locals: {commentable: @commentable}
== render partial: '/comments/form'

View File

@ -0,0 +1 @@
== render partial: 'thread', locals: {commentable: @commentable, type: 'user'}

View File

@ -9,8 +9,9 @@
.form-horizontal .form-horizontal
.form-group .form-group
.field .field
= f.autocomplete_field :client, autocomplete_client_name_contacts_path, :id_element => '#contact_client_id', class: "form-control", placeholder: "Client Name"
= f.label :client_id, class: "sr-only" = f.label :client_id, class: "sr-only"
= f.text_field :client_id, class: "form-control", placeholder: "Client ID" = f.text_field :client_id, class: "form-control sr-only", placeholder: "Client ID"
.form-inline .form-inline
.form-group .form-group
.field .field

View File

@ -7,10 +7,6 @@
li = message li = message
.form-horizontal .form-horizontal
.form-group
.field
= f.label :ticket_id, class: "sr-only"
= f.text_field :ticket_id, class: "form-control", placeholder: "Master Ticket id"
.form-group .form-group
.field .field
= f.label :creator_type, class: "sr-only" = f.label :creator_type, class: "sr-only"

View File

@ -14,7 +14,6 @@ table.table.table-condensed.
th th
th th
th th
th
tbody tbody
- @tickets.each do |ticket| - @tickets.each do |ticket|
@ -22,17 +21,16 @@ table.table.table-condensed.
td = link_to("##{ticket.id}", ticket) td = link_to("##{ticket.id}", ticket)
td = link_to_creator(ticket) td = link_to_creator(ticket)
td = link_to ticket.title, ticket td = link_to ticket.title, ticket
td = ticket.tickets.empty? ? ticket.description : ticket.tickets.first.description td = ticket.short_description
- if ticket.state == Ticket::CLOSE - if ticket.state == Ticket::CLOSE
td.bg-danger = ticket.state td.bg-danger = ticket.state
- else - else
td.bg-success = ticket.state td.bg-success = ticket.state
td = ticket.updated_at.to_s(:long) td = ticket.updated_at.to_s(:long)
td = ticket.last_response ? distance_of_time_in_words_to_now(ticket.last_response.updated_at) : "never" td = ticket.comments.empty? ? "never" : distance_of_time_in_words_to_now(ticket.comments.first.updated_at)
td = link_to 'Show', ticket td = link_to 'Show', ticket
td = link_to 'Edit', edit_ticket_path(ticket) td = link_to 'Edit', edit_ticket_path(ticket)
td = link_to 'Destroy', ticket, data: {:confirm => 'Are you sure?'}, :method => :delete td = link_to 'Destroy', ticket, data: {:confirm => 'Are you sure?'}, :method => :delete
td = link_to 'Respond', ticket_respond_path(ticket) if ticket.open?
- if ticket.open? - if ticket.open?
td = link_to 'Close', ticket_close_path(ticket), data: {:confirm => 'Are you sure?'}, :method => :patch td = link_to 'Close', ticket_close_path(ticket), data: {:confirm => 'Are you sure?'}, :method => :patch
- elsif ticket.close? - elsif ticket.close?

View File

@ -1,19 +1,16 @@
h1.page-header = "Show ticket: #{@ticket.head.title}" h1.page-header = "Show ticket: #{@ticket.title}"
p p
strong strong
| Id: # | Id: #
= @ticket.id = @ticket.id
p
strong Réponse à:
= link_to @ticket.head.title, @ticket.head
p p
strong State: strong State:
- if @ticket.head.state == Ticket::CLOSE - if @ticket.state == Ticket::CLOSE
td.bg-danger = @ticket.head.state td.bg-danger = @ticket.state
- else - else
td.bg-success = @ticket.head.state td.bg-success = @ticket.state
p p
strong Creator: strong Creator:
@ -29,38 +26,13 @@ p
strong State: strong State:
= @ticket.state = @ticket.state
table.table.table-condensed.
thead
tr
th Creator
th Title
th Description
th Last update
th
th
th
tbody
- @ticket.tickets.each do |ticket|
tr
td = link_to_creator(ticket)
td = link_to ticket.title, ticket
td = ticket.description
- if ticket.state == Ticket::CLOSE
td.bg-danger = ticket.state
- else
td.bg-success = ticket.state
td = ticket.updated_at.to_s(:long)
td = link_to 'Show', ticket
td = link_to 'Edit', edit_ticket_path(ticket)
td = link_to 'Destroy', ticket, data: {:confirm => 'Are you sure?'}, :method => :delete
br br
- if @ticket.open? - if @ticket.open?
= link_to 'Respond', ticket_respond_path(@ticket), class: 'btn btn-sm btn-default'
= link_to 'Close', ticket_close_path(@ticket), method: :patch, class: 'btn btn-sm btn-success' = link_to 'Close', ticket_close_path(@ticket), method: :patch, class: 'btn btn-sm btn-success'
- else - else
= link_to 'Reopen', ticket_open_path(@ticket), method: :patch, class: 'btn btn-sm btn-danger' = link_to 'Reopen', ticket_open_path(@ticket), method: :patch, class: 'btn btn-sm btn-danger'
= link_to 'Edit', edit_ticket_path(@ticket), class: 'btn btn-sm btn-default' = link_to 'Edit', edit_ticket_path(@ticket), class: 'btn btn-sm btn-default'
= link_to 'Back', tickets_path, class: 'btn btn-sm btn-default' = link_to 'Back', tickets_path, class: 'btn btn-sm btn-default'
== render partial: "/comments/thread", locals: {commentable: @ticket, type: 'admin'}

View File

@ -1,3 +1,3 @@
# Be sure to restart your server when you modify this file. # Be sure to restart your server when you modify this file.
Rails.application.config.session_store :cookie_store, key: '_WebImmo_session' Rails.application.config.session_store :cookie_store, key: '_MorningPeak_session'

View File

@ -2,15 +2,23 @@ Rails.application.routes.draw do
root to: "home#index" root to: "home#index"
match "/help", to: "home#help", via: [:get], as: 'help' match "/help", to: "home#help", via: [:get], as: 'help'
resources :comments
# ----- ADMINISTRATION ----- # ----- ADMINISTRATION -----
resources :tickets do resources :tickets do
patch :close patch :close
patch :open patch :open
get :respond resources :comments do
collection do
get 'about'
end
end
end end
resources :comments
resources :contacts do resources :contacts do
get :autocomplete_client_name, :on => :collection
resources :comments do resources :comments do
collection do collection do
get 'about' get 'about'
@ -20,6 +28,7 @@ Rails.application.routes.draw do
match '/contacts/:id/view', to: 'contacts#view', via: [:patch, :get], as: 'view_contact' match '/contacts/:id/view', to: 'contacts#view', via: [:patch, :get], as: 'view_contact'
resources :bills do resources :bills do
get :autocomplete_client_name, :on => :collection
resources :comments do resources :comments do
collection do collection do
get 'about' get 'about'
@ -28,6 +37,7 @@ Rails.application.routes.draw do
end end
resources :clients do resources :clients do
get :autocomplete_contact_name, :on => :collection
resources :comments do resources :comments do
collection do collection do
get 'about' get 'about'
@ -39,6 +49,7 @@ Rails.application.routes.draw do
match "/users/dashboard", to: 'home#user_dashboard', via: [:get], as: 'users_dashboard' match "/users/dashboard", to: 'home#user_dashboard', via: [:get], as: 'users_dashboard'
match "/users", to: redirect('/users/dashboard'), via: [:get] match "/users", to: redirect('/users/dashboard'), via: [:get]
devise_for :users devise_for :users
match "/admins/dashboard", to: 'home#admin_dashboard', via: [:get], as: 'admins_dashboard' match "/admins/dashboard", to: 'home#admin_dashboard', via: [:get], as: 'admins_dashboard'
match "/admins", to: redirect('/admins/dashboard'), via: [:get] match "/admins", to: redirect('/admins/dashboard'), via: [:get]
match "/admins/export", to: "home#export", via: [:get], as: 'admins_export' match "/admins/export", to: "home#export", via: [:get], as: 'admins_export'
@ -48,62 +59,12 @@ Rails.application.routes.draw do
resources :client_tickets, path: '/client/tickets' do resources :client_tickets, path: '/client/tickets' do
patch :close patch :close
patch :open patch :open
get :respond resources :comments do
collection do
get 'about', to: 'comments#about_client'
end
end
end end
resources :client_bills, path: '/client/bills' resources :client_bills, path: '/client/bills'
# The priority is based upon order of creation: first created -> highest priority.
# See how all your routes lay out with "rake routes".
# You can have the root of your site routed with "root"
# root 'welcome#index'
# Example of regular route:
# get 'products/:id' => 'catalog#view'
# Example of named route that can be invoked with purchase_url(id: product.id)
# get 'products/:id/purchase' => 'catalog#purchase', as: :purchase
# Example resource route (maps HTTP verbs to controller actions automatically):
# resources :products
# Example resource route with options:
# resources :products do
# member do
# get 'short'
# post 'toggle'
# end
#
# collection do
# get 'sold'
# end
# end
# Example resource route with sub-resources:
# resources :products do
# resources :comments, :sales
# resource :seller
# end
# Example resource route with more complex sub-resources:
# resources :products do
# resources :comments
# resources :sales do
# get 'recent', on: :collection
# end
# end
# Example resource route with concerns:
# concern :toggleable do
# post 'toggle'
# end
# resources :posts, concerns: :toggleable
# resources :photos, concerns: :toggleable
# Example resource route within a namespace:
# namespace :admin do
# # Directs /admin/products/* to Admin::ProductsController
# # (app/controllers/admin/products_controller.rb)
# resources :products
# end
end end

View File

@ -0,0 +1,8 @@
class UpdateTickets < ActiveRecord::Migration
def change
rename_column :tickets, :head_creator_view_at, :creator_view_at
remove_column :tickets, :ticket_id
end
end

View File

@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150725193246) do ActiveRecord::Schema.define(version: 20160131000119) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@ -41,7 +41,7 @@ ActiveRecord::Schema.define(version: 20150725193246) do
t.text "description" t.text "description"
t.integer "amount" t.integer "amount"
t.boolean "paid", default: false, null: false t.boolean "paid", default: false, null: false
t.date "emission_date", default: '2015-07-24', null: false t.date "emission_date", default: '2016-01-30', null: false
t.date "due_date", null: false t.date "due_date", null: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
@ -96,18 +96,16 @@ ActiveRecord::Schema.define(version: 20150725193246) do
create_table "tickets", force: :cascade do |t| create_table "tickets", force: :cascade do |t|
t.integer "creator_id" t.integer "creator_id"
t.string "creator_type" t.string "creator_type"
t.integer "ticket_id"
t.string "title" t.string "title"
t.text "description" t.text "description"
t.string "state", default: "open", null: false t.string "state", default: "open", null: false
t.time "admin_view_at" t.time "admin_view_at"
t.time "head_creator_view_at" t.time "creator_view_at"
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
end end
add_index "tickets", ["creator_type", "creator_id"], name: "index_tickets_on_creator_type_and_creator_id", using: :btree add_index "tickets", ["creator_type", "creator_id"], name: "index_tickets_on_creator_type_and_creator_id", using: :btree
add_index "tickets", ["ticket_id"], name: "index_tickets_on_ticket_id", using: :btree
create_table "users", force: :cascade do |t| create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false t.string "email", default: "", null: false
@ -129,5 +127,4 @@ ActiveRecord::Schema.define(version: 20150725193246) do
add_foreign_key "bills", "clients" add_foreign_key "bills", "clients"
add_foreign_key "contacts", "clients" add_foreign_key "contacts", "clients"
add_foreign_key "tickets", "tickets"
end end