-- Ticket tracker
-- v 2.2
-- create an administration group for ticket tracker administration

begin
   administration_group_add ('Ticket Admin Staff', short_name_from_group_name('ticket'), 'ticket', NULL, 'f', '/ticket/admin/');
end;
/


create sequence ticket_project_id_sequence start with 1;

create table ticket_projects (
	project_id	integer not null primary key,
	title		varchar(100),
	-- person who request the project and will be the owner
	customer_id	integer not null references users,
	start_date	date,
	end_date	date,
	-- person who gets defaultly assigned to new tickets in the project	
	default_assignee integer references users,
	group_id	references user_groups
);

-- we need at least one project in any system, "Incoming" for 
-- random incoming email

-- since this has a hard-wired project_id, constrained to be primary 
-- key, we're not in any danger of creating dupe projects

insert into ticket_projects 
(project_id, customer_id, title, start_date)
values
(0, system_user_id, 'Incoming', sysdate);

-- A table to assign people to projects

create sequence ticket_assignment_id_sequence;

create table ticket_assignments (
	assignment_id	integer not null primary key,
	project_id	integer references ticket_projects,
	user_id	 	integer references users,
	rate		integer, -- e.g. 125
	purpose		varchar(4000), -- e.g. "HTML, Java, etc..."
	-- we add this active flag in case someone gets taken off the
	-- project.
	active_p	char(1) check (active_p in ('t','f'))
);


-------------- From The Community System ---------------
-- table state, country_codes, users
--------------------------------------------------------

create table ticket_priorities (
        priority                integer not null primary key,
        name                    varchar(20)
);

insert into ticket_priorities values (3, 'low');
insert into ticket_priorities values (2, 'medium');
insert into ticket_priorities values (1, 'high');

create sequence ticket_issue_id_sequence;

create table ticket_issues (
        msg_id                  integer not null primary key,
        project_id              integer not null references ticket_projects,
        user_id                 references users,
	group_id		references user_groups,
        posting_time            date not null,
        modification_time       date,
	ticket_type		varchar(100), -- {ticket, service_ticket, bug, feature_request}
        one_line                varchar(700),
        message                 clob default empty_clob(),
        indexed_stuff           clob default empty_clob(), -- for context index
        close_date              date,
        closed_by               integer references users,
        -- When it is important for it to be finished.
        deadline                date,
	-- Status: open, waiting assignment, development, fixed waiting approval, closed 
	status			varchar(100),
        priority                integer not null references ticket_priorities,
	severity		varchar(100),
	-- who was responsible for creating this message
        source                  varchar(100), 
	-- user name who last modified 
        last_modified_by        varchar(200), 
	-- When was the last "nag" notification sent 
	last_notification	date,
	-- Ticket author's contact info
	contact_name		varchar(200),
	contact_email		varchar(200),
	contact_info1		varchar(700),
	contact_info2		varchar(700),
	-- product-specific fields
	data1			varchar(700),
	data2			varchar(700),
	data3			varchar(700),
	data4			varchar(700),
	data5			varchar(700),
	-- is this ticket visible to customers
	public_p		char(1) default('t') check(public_p in ('t','f')),
	-- if notify_p is 't', member of that project will receive notification email
	notify_p		char(1) default('t') check(notify_p in ('t','f'))
);


create or replace trigger ticket_modification_time
before insert or update on ticket_issues
for each row
when (new.modification_time is null)
begin
 :new.modification_time :=SYSDATE;
end;
/
show errors

-- the ticket_changes table can reference ticket_issues
-- but only in Oracle 8.1.5 or newer; Oracle 8.0.5 gets 
-- bent out of shape with a mutating trigger from
-- ticket_activity_logger

--- keep track of changes to a ticket
create table ticket_changes (
  msg_id    integer not null, -- references ticket_issues
  who 	    varchar(256),
  what      varchar(256),
  old_value varchar(256),
  new_value varchar(256),
  modification_date  date
);

create index ticket_changes_by_msg_id on ticket_changes(msg_id);

-- track changes to tickets
create or replace trigger ticket_activity_logger
after update on ticket_issues
for each row
begin
  if (:old.project_id <> :new.project_id) then
   insert into ticket_changes (msg_id, who, what, old_value, new_value, modification_date)
   values
   (:new.msg_id, :new.last_modified_by, 'Project ID', :old.project_id, :new.project_id, sysdate);
  end if;

  if (:old.ticket_type <> :new.ticket_type) then
   insert into ticket_changes (msg_id, who, what, old_value, new_value, modification_date)
   values
   (:new.msg_id, :new.last_modified_by, 'Ticket Type', :old.ticket_type, :new.ticket_type, sysdate);
  end if;

  if (:old.one_line <> :new.one_line) then
   insert into ticket_changes (msg_id, who,what, old_value, new_value, modification_date) 
   values
   (:new.msg_id, :new.last_modified_by, 'Synopsis', :old.one_line, :new.one_line, sysdate);
  end if;

  if (:old.deadline <> :new.deadline) then
   insert into ticket_changes (msg_id, who,what, old_value, new_value, modification_date) 
   values
   (:new.msg_id, :new.last_modified_by, 'Deadline', :old.deadline, :new.deadline, sysdate);
  end if;

  if (:old.status <> :new.status) then
   insert into ticket_changes (msg_id, who,what, old_value, new_value, modification_date) 
   values
   (:new.msg_id, :new.last_modified_by, 'Status', :old.status, :new.status, sysdate);
  end if;

  if (:old.priority <> :new.priority) then
   insert into ticket_changes (msg_id, who,what, old_value, new_value, modification_date) 
   values
   (:new.msg_id, :new.last_modified_by, 'Priority', :old.priority, :new.priority, sysdate);
  end if;

  if (:old.severity <> :new.severity) then
   insert into ticket_changes (msg_id, who,what, old_value, new_value, modification_date) 
   values
   (:new.msg_id, :new.last_modified_by, 'Severity', :old.severity, :new.severity, sysdate);
  end if;

-- These are custom fields -- the column title will need  to
--  be kept up to date 
-- manually 


  if (:old.data1 <> :new.data1) then
   insert into ticket_changes (msg_id, who,what, old_value, new_value, modification_date) 
   values
   (:new.msg_id, :new.last_modified_by, 'Hardware_model', :old.data1, :new.data1, sysdate);
  end if;

  if (:old.data2 <> :new.data2) then
   insert into ticket_changes (msg_id, who,what, old_value, new_value, modification_date) 
   values
   (:new.msg_id, :new.last_modified_by, 'Software_version', :old.data2, :new.data2, sysdate);
  end if;

  if (:old.data3 <> :new.data3) then
   insert into ticket_changes (msg_id, who,what, old_value, new_value, modification_date) 
   values
   (:new.msg_id, :new.last_modified_by, 'Software_version', :old.data2, :new.data2, sysdate);
  end if;

  if (:old.data4 <> :new.data4) then
   insert into ticket_changes (msg_id, who,what, old_value, new_value, modification_date) 
   values
   (:new.msg_id, :new.last_modified_by, 'Build', :old.data4, :new.data4, sysdate);
  end if;
end;
/
show errors





--- a table to assign users to  issues
--- the selection list for this will be the
--- ticket_assignments table constrained by the appropriate project


create table ticket_issue_assignments (
	msg_id		integer not NULL references ticket_issues,
	user_id		integer not null references users,
	purpose		varchar(4000), -- e.g. "HTML, Java, etc..."
	-- we add this active flag in case someone gets taken off the
	-- issue.
	active_p	char(1) check (active_p in ('t','f')),
	unique (msg_id, user_id)
);

-- cross reference table mapping issues to other issues
create table ticket_xrefs (
       from_ticket references ticket_issues(msg_id),
       to_ticket references ticket_issues(msg_id)
);


create sequence ticket_response_id_sequence;

create table ticket_issue_responses (
        response_id             integer not null primary key,
        response_to             integer not null references ticket_issues,
        user_id                 references users,
        posting_time            date not null,
	public_p		char(1) default('t') check(public_p in ('t','f')),
        message                 clob default empty_clob()
);


-- update the ticket's modification timestamp
create or replace trigger response_modification_time
before insert or update on ticket_issue_responses
for each row
begin
  update ticket_issues set modification_time = SYSDATE 
  where msg_id = :new.response_to;
end;
/
show errors


create table ticket_issue_notifications (
        msg_id                  integer not null references ticket_issues,
        user_id                 integer not null references users,
        primary key (msg_id, user_id)
);


-- called by /tcl/email-queue.tcl 
-- and /ticket/issue-response-2.tcl 
create or replace procedure ticket_update_for_response(v_response_id IN integer)
AS
 v_response_row ticket_issue_responses%ROWTYPE;
 v_indexed_stuff clob;
BEGIN
 select ticket_issue_responses.* into v_response_row
   from ticket_issue_responses
   where response_id = v_response_id;

 if v_response_row.message is not null then 
   select indexed_stuff into v_indexed_stuff
     from ticket_issues
     where msg_id = v_response_row.response_to
     for update;
   dbms_lob.append(v_indexed_stuff, v_response_row.message);
 end if;
END;
/
show errors


create or replace function ticket_one_if_high_priority (priority IN integer, status IN varchar)
return integer
is
BEGIN
  IF ((priority = 1) AND (status <> 'closed') AND (status <> 'deferred')) THEN
    return 1;
  ELSE 
    return 0;   
  END IF;
END ticket_one_if_high_priority;
/
show errors

create or replace function ticket_one_if_blocker (severity IN varchar, status IN varchar)
return integer
is
BEGIN
  IF ((severity = 'showstopper') AND (status <> 'closed') AND (status <> 'deferred')) THEN
    return 1;
  ELSE 
    return 0;   
  END IF;
END ticket_one_if_blocker;
/
show errors

