pax_global_header 0000666 0000000 0000000 00000000064 14575002472 0014520 g ustar 00root root 0000000 0000000 52 comment=7a3745a8ba264bc9d3fbd2483f114efc7c189384
acs-workflow-master/ 0000775 0000000 0000000 00000000000 14575002472 0014773 5 ustar 00root root 0000000 0000000 acs-workflow-master/README.md 0000664 0000000 0000000 00000233375 14575002472 0016267 0 ustar 00root root 0000000 0000000 # Introduction to ]po[ Petri-Net Workflows
This package is part of ]project-open[, an open-source enterprise project management system.
For more information about ]project-open[ please see:
* [Documentation Wiki](https://www.project-open.com/en/)
* [V5.0 Download](https://sourceforge.net/projects/project-open/files/project-open/V5.0/)
* [Installation Instructions](https://www.project-open.com/en/list-installers)
About Introduction to ]po[ Petri-Net Workflows :
This document provides a quick overview of contents of the ]project-open[ workflow package.
# Online Reference Documentation
## What is a Workflow?
## Elements of a Workflow
## Workflows and Business Objects
## Starting a Workflow for a ]project-open[ Objects
## The Inbox - Interacting With Users
## Assignments - Who Should Take Action?
## Panels - Working with User Input
## Callbacks - Taking Action
## Pre-configured Workflows
## Procedure Files
Takes a name (split in two parts) and makes it unique with respect to the list passed in <code>taken_names</code>, by putting an integer number between <code>name_part_one</code> and <code>name_part_two</code>, chopping <code>name_part_one</code> as required to stay within maxlen.
Splits a URL including query arguments (e.g., /foo/bar?baz=greble&yank=zazz) up into a list of lists of name/value pairs, that can be passed as an argument to export_vars.
We store tasks in a client property as a list of array gets with the keys: task_name, transition_key, task_time, loop_to_transition_key, loop_question, loop_answer, assigning_transition_key.
Admin big picture view of a workflow, including places, transitions and arcs
acs-workflow-master/acs-workflow.info 0000664 0000000 0000000 00000006742 14575002472 0020277 0 ustar 00root root 0000000 0000000
GPL V2.0 or any later versionPetri-Net WorkflowPetri-Net Workflowftacs-workfloworaclepostgresqlLars PindNeophytos DemetriouDaniel WickstromFrank BergmannProvides Petri-Net workflow management features to all ACS objects.2002-05-15OpenACS
acs-workflow-master/catalog/ 0000775 0000000 0000000 00000000000 14575002472 0016405 5 ustar 00root root 0000000 0000000 acs-workflow-master/catalog/acs-workflow.da_DK.ISO-8859-1.xml 0000664 0000000 0000000 00000000425 14575002472 0023711 0 ustar 00root root 0000000 0000000
Del afPå hvad?Aktivitet
acs-workflow-master/catalog/acs-workflow.de_DE.ISO-8859-1.xml 0000664 0000000 0000000 00000055302 14575002472 0023713 0 ustar 00root root 0000000 0000000
1 activer Fall1 Fall total, also dieAktionAktion:Typ AktionAktionenAktionenDatum AktivierungAktive AufgaenNeuNeue KanteNeue ZuweisungNeues AttributNeues AttributNeuer KontextNeue GruppeNeuer WächterNeue SchleifeNeues PanelNeues PanelNeues PanelNeue PersonNeuer PlatzNeue RolleNeue RolleNeue AufgabeNeue TransitionAdmin WorkflowsAdminAlle AttributeAlle Aufgabenund einarc.guard_descriptionAls Teil vonSelbstzuweisungZugewiesenZuweisungZuweisungAttributName Attributattribute.nameAttributeAttributevonNach RolleabbrechenAufgabe abbrechenAbgebrochen(kann keinen neue Kante hinzufügen)(kann Kante nicht löschen)(kann Platz nicht löschen)FallFall startenFälleZustand ändern:ändern auf manuellKommentarVerbrauchtKontextcontext.context_keykopieren - einfügenneuer KontextAktuelle ZuweisungAktueller WertZusatzargumentDatentypinaktive TokenFristFristenFall debuggenVorlage Wertlöschenalle Fälle löschenKante löschenWächter löschenPlatz löschenAufgabe löschenBeschreibungBeschreibung:Anzeigen: [Schleife erfolgreich hinzugefügtFertig beiFertig DatumRunterladenÄnderneditierenBearbeitenKante bearbeitenWächter bearbeitenName bearbeitenPanel bearbeitenProzessname bearbeitenEffektive ZuweisungAktivierenAktiviertProzess exportierenExtreme AktionenFeuerfeuernGehe zurückWächter BedingungKopfzeilegehalten vonWeiter wenn SieHalten AuszeitHalterFall initialisierenEingangsortAnweisungeneses zu einer DateiJournalSchlüsselletzt(e/er)Aktive TokenGebundenSchleifeSchleife von AufgabeSchleife zu AufgabeSchleifen, oder Sie können den erweiterten Prozess Builder jetzt gleich starten, also wollen Sie wahrscheinlich, wie z.B. 'Bestätigt'?`In Abhängigkeit von der Antwort wird der Workflow entweder zu %loop_to_task_name%' oder %loop_next_pretty% fortschreiten.. Dies ist kaum genug um zu nennen...Wir werden den Benutzer Fragen stellen, die er mit Ja oder Nein beantworten kann. Ja führt zur selben Aufgabe zurück, während Nein den Prozess beendet, oder anders herum. Sie entscheiden das im Folgenden.Ein Wächter ist eine SQL-Bedingung, die erfüllt sein muss, damit sich ein Token über die Kante bewegen kannEine Schleife geht immer zurück zuNeue Schleife von '%loop_from_task_name%' zurück zu sich selbstNeue Zuweisung: %tasks.user_select_widget%%add_export_vars;noquote% Setzen auf:Neue Schleife von %task_name;noquote%Erweiterter ProzessdefinitionAlle Transitionen aktivierenAlle Parteien sind bereits dem Task zugewiesenZuweisen von anderer Transition%assign_export_vars;noquote% Zuweisen zu:%role_name;noquote% zuweisen%task_roles_to_assign.role_name% zuweisenWeisen Sie die folgenden Rollen zuZuweisen der Transition an %role.role_name;noquote%Zugewisen durch folgende Transitionen:Zuweisungen für %case.object_name;noquote% caseZuweisungen noch durchzuführen von %transition_name;noquote%am %task.finished_date_pretty%Attribute für %workflow_name;noquote%Attribute, die durch %transition_name;noquote% gesetzt werdenAdmin Business ProzesseBusiness Prozesse auf diesem SystemFall: %case.object_name;noquote% (%case.state;noquote%)%case.object_name;noquote% Fristen%case.object_name;noquote% Falländern auf programmatisch%case.object_name;noquote% kommentierenEntnehmende TransitionenFrist ist %task.deadline_pretty%Gesamten Prozess löschen(Hängt von der oben gewählten Bedingung ab)Rolle %role_name;noquote% bearbeitenDiese PL/SQL Prozedur wird ausgeführt, wenn %transition_name% aktiviert wird. Dies ist nützlich z.B. um eine Status automatisch zu ändern.Alle möglichen Parteien sind bereits zugewiesenBusiness Prozess exportierenzurückgehen und weitere Aufgaben definierenzurückgehen und Aufgaben definierenZu %tasks.loop_to_task_name% gehen wennzur Business Prozess Administrationsseite gehenGraphischer Prozess Editor(gehalten von Aufgabe %live_tokens.locked_task_id%)Hier sind Hilfestellungen für die FreigabeHier sind Informationen über die Ausgaben(Wenn der Benutzer antwortet was Sie hier spezifiziert haben, dann machen wir eine Schleife zurück. Wenn er eine andere Antwort gibt, dann machen wir weiter mit der nächsten Aufgabe.)Wenn Sie darauf bestehen nur eine Aufgabe zu wollen, dann ist das OK. Sie können sogarWenn Sie einen erweiterten Prozess erstellen wollen, dann können Sie hier starten und später Flexibilität hinzufügen mitIn der Praxis wird jedesmal automatisch ein neuer Business Prozess gestartet, wenn jemand ein Objekt anlegt.In der Liste unten, bitte neue Schleife hinzufügenin dem Prozess, also von '%loop_from_task_name%' bis '%loop_to_task_name%'.
Ob wir der Schleife zurück folgen zu '%loop_to_task_name%' oder vorwärts zum nächsten %loop_next_pretty% gehen hängt von der Person ab, die '%loop_from_task_name%' durchführt.
Schleife zurück, wenn die Antwort istloop.to_transition_key(machen Sie eine Ja/Nein Frage, also z.B. "Freigegeben")Manuell zuweisen %role_name;noquote%Keine Attribute definiertKein Business Prozess installiertKeine Zuweisungenkeine aktiven TransitionenKeine Rollen von dieser Aufgabe zugewiesen(keine Sonderzeichen)keine statischen ZuweisungenBisher keine Aufgaben beendetKeine Transition gehört zu dieser RolleKeine Transitionen definiertKeine Zuweisung zu irgendeiner RolleAchtung: Diese Seite ist nicht Teil der endgültigen Benutzeroberfläche(Achtung, Sie können mit Schleifen nur rückwärts springen)an %task.canceled_date_pretty%Nur anzeigen, wenn die Aufgabe gestartet wurde?oder Attributnamen benutzenStandard Aktionspanel überschreiben?überschreiben %panels.overrides_action_p%; whenstarted=%panels.only_display_when_started_p%Panele für %transition_name;noquote%Platz %place_name;noquote%Platz: %place.place_name% (BeschreibungBitte einen Namen für die neue Rolle eingebenErzeugende TransitionProgrammatische ZuweisungWählen Sie eine Aufgabe, der Sie die Rolle %role_name% zuweisen wollen:Statische ZuweisungSQL in einem <textarea> Feld anzeigen, so dass Sie könnenEinfacher Prozess Wizard Schritt 5: Neuer %workflow_name;noquote%Einfacher Prozess WizardEinfacher Prozess Wizard Schritt 3: Schleifen für %workflow_name;noquote%Aufgabe: %tasks.transition_name%Aufgabe %transition_name;noquote%Aufgabe: %transition.transition_name% (Aufgaben, an denen Sie gerade arbeitendie zu einer vorherigen Aufgabe zurückgehen. Schließlich können sie aufsetzen ...Als ersten Schritte bitte Namen und Beschreibung eingeben.Der erste Schritt ist zu geben ...das SQL Script in Ihrem Browserdie Aufgabe von der Sie aus eine Schleife beginnen wollenDer Benutzer, der die Aufgabe ausführtDer Fall ist in Zustand %case.state%(dies ist die einzige Aufgabe, zu der Sie von hier zurückspringen können)Diese Aufgabe wurde abgebrochen vonDiese Aufgabe wurde beendet vonDies exportiert den Business Prozess als SQL Script, das Sie auch auf anderen Systemen ausführen können.(Die will normalerweise die Form annehmenDieser Wizard erlaubt, schnell einen einfachen Business Prozess zu definieren. Später können Sie hinzufügen...um in Reihenfolge ausgeführt zu werden, und Sie können hinzufügen...zu Ihrem Business Prozess.Token auf Platz %live_tokens.place_key% (%live_tokens.state%)Dies ist der aktuelle Weg einen Fall zu starten. Bitte wählen Sie ein Objekt ... Wir benutzen es, um dem Benutzer zu sagen, woran er arbeitet.ansehen oder ändern der Definition%workflow_name% - %transition_name% - Aufgabe Aktionen%workflow_name;noquote% Fälle%workflow_name;noquote% statische Zuweisungen%workflow.num_active_cases% aktive Fälle%workflow.num_cases% Fälle insgesamt%workflow.pretty_name;noquote% - Prozess Wizard%workflows.num_cases% aktive Fälle%workflows.num_unassigned_tasks% Aufgabe ohne Zuweisungworkflow.workflow_nameSie haben die Aufgabe abgebrochen am %task.canceled_date_pretty%.Sie haben die Aufgabe erledigt am %task.canceled_date_pretty%.Sie haben noch keine Aufgabe definiert. BitteIhr neuer Business Prozess ist fertig.eine Kopie machenManuellManuelle ZuweisungManuelle ZuweisungenMinutennach ObenNameNameEinfacher ProzessErweiterter ProzessNeuer Erweiterter ProzessNein.Nein.Nein/>Nein\>NeinKeine aktiven FälleKeine aktiven Aufgabenkeine ZuweisungenKeine Attributekeine Attributekeine FristKeine alten FälleKeine PanelsKeine Rollen definiertKeine Aufgabenkeine Aufgabenkeine TokenKeine TransitionenKeine Aufgaben ohne Zuweisungnichtnicht gestartetHinweis!Benachrichtigungjetzt.ObjektObjekttypauf dem Serverauf was?eine Aufgabe definiert(optional)Optionales Argumentoptionale BeschreibungOptionenReihenfolgeAusgangsorteBeide Panels überschreiben?package-name/packages/Partei zum zuweisenVergangene AufgabenPlatzName PlatzPL/SQL ProzedurHübscher Namevorige AufgabeProzessProzessProzessnameProzessname:Prozess ZustandProduziert(Frage)zu fragende Frageneu zuweisenAufgabe neu zuweisenEntfernenentfernenSchleife entfernenRolleRollennamezuzuweisende RolleRollenRegelnSpeichernMethode auswählenFrist setzenSeitSortierreihenfolgespezieller PlatzNeuen Fall startenGestartetDatum GestartetStatusStatischStatische ZuweisungStatische ZuweisungenAufgabeAufgabe fertigAufgabe in der SchleifeAufgabennameAufgabennameAufgabe nicht gefundenDieser Fehler kann auftreten, wenn der System Administrator einen Workflow gelöscht hat.<br>Diese Situation sollte während des normalen Betriebs nicht auftreten.<p>Bitte kontaktieren Sie Ihren System Administrator.Aufgabenzu erledigende AufgabenName VorlagenURL Vorlagedas SQL ScriptZeitGeschätzte Zeitgeschätzte ZeitFristTo DoTokenTransitionPanel für TransitionTransitionenTriggerTriggertypNicht zugewiesenAufgabe ohne ZuweisungAufgaben ohne ZuweisungURLBenutztWertSichtWir werden ihn fragenwird gefragt werden zuArbeitslisteWorkflowWorkflow FallWorkflows/www/Ja/>Ja\>JaJa/Nein FrageSie können jetztSie brauchen nur
acs-workflow-master/catalog/acs-workflow.en_US.ISO-8859-1.xml 0000664 0000000 0000000 00000053677 14575002472 0024001 0 ustar 00root root 0000000 0000000
1 active case1 case total, i.e. theActionAction:Action TypeActionsactionsActivated DateActive TasksAddadd arcAdd AssigneeAdd attributeadd attributeAdd Contextadd groupadd guardadd loopAdd PanelAdd paneladd paneladd personAdd PlaceAdd Roleadd roleAdd Taskadd transitionAdmin WorkflowsAdministerAll AttributesAll Tasksand anarc.guard_descriptionPart ofassign yourselfAssigneesassignmentAssignmentsAttributeAttribute nameattribute.nameAttributesattributesbyBy Rolecancelcancel taskCanceled(can't add arc)(can't delete arc)(can't delete place)CaseCase startedCasesChange state:change to manualCommentConsumedContextcontext.context_keycopy and pastecreate new contextCurrent AssigneesCurrent ValueCustom argumentDatatypeDead TokensDeadlineDeadlinesdebug caseDefault valuedeletedelete all casesdelete arcdelete guarddelete placedelete taskDescriptionDescription:Display: [done adding loopsDone ByDone DateDownloadEdit:editEditEdit Arcedit guardedit nameEdit panelEdit Process NameEffective AssigneesEnableEnabledexport processExtreme ActionsFirefireGo backGuard conditionHeaderHeld byHit Next when you'reHold TimeoutHolderInitialize CaseInput PlacesInstructionsitit to a fileJournalKeylastLive TokensLockedLoopLoop from taskLoop to taskloops, or
you can start with the Advanced Process Builder right away., so you probably want to, such as
'Approved?'. Depending on the answer, we'll go to either
'%loop_to_task_name%' or %loop_next_pretty%.. That's barely
enough to call a. The
way it works is that we'll ask the user some question, to which he
answers yes or no. If he answers yes, we'll go back to the same task again,
if he answers no, we'll continue to finish the process—or
vice versa. You get to decide that.A guard is some condition that must be satisfied for a token to travel over that arc.A loop always goes back to someadd a loop from '%loop_from_task_name%' back to itselfAdd assignee: %tasks.user_select_widget%%add_export_vars;noquote%
Set this:Add Loop from %task_name;noquote%Advanced Process BuilderAll Enabled TransitionsAll parties are already assigned to this taskassign by another transition%assign_export_vars;noquote%
Assign this:Assign %role_name;noquote%Assign %task_roles_to_assign.role_name%assign the following rolesAssign Transition to %role.role_name;noquote%Assigned by these transitions:Assignments for %case.object_name;noquote% caseAssignments to be done by %transition_name;noquote%at %task.finished_date_pretty%Attributes for %workflow_name;noquote%Attributes to be set by %transition_name;noquote%Business Process AdministrationBusiness Processes on This SystemCase: %case.object_name;noquote% (%case.state;noquote%)%case.object_name;noquote% Deadlines%case.object_name;noquote% casechange to programmaticComment on case %case.object_name;noquote%Consuming TransitionsDeadline is %task.deadline_pretty%delete process entirely(Depends on the condition chosen above)Edit %role_name;noquote% roleThis PL/SQL proc will be executed when %transition_name% is enabled. Useful for e.g. automatically changing a status.Every possible assignee is already assignedExport Business Processgo back and define more tasksgo back and define some tasksGo to %tasks.loop_to_task_name% ifgo to the business process administration pagegraphic process editor(held by task %live_tokens.locked_task_id%)Here are some logic and aids for the approval.Here's some information about the expense claim.(If the user answers what you specify here, we'll loop back. If he choses the other answer, we'll continue with the next task.)If you insist that you only want one task, that's fine. You can
evenIf you want to create more advanced processes, you can either start
here and add flexibility later using theIn real life, what will happen is that every time a new ticket (in the ticket-tracker),
a new application (for a job applicant management application) is created, we automatically initialize
a business process case for that object.In the list below, hit add loop onin the process, e.g. from
'%loop_from_task_name%' to '%loop_to_task_name%'. Whether we loop back
to '%loop_to_task_name%' or go forward to %loop_next_pretty% is up to
the person performing '%loop_from_task_name%'.Loop back if answer isloop.to_transition_key(make it a yes/no-question, e.g. "Approved")Manually Assign %role_name;noquote%No attributes definedno business processes installedno effective assigneesno enabled transitionsNo roles to be assigned by this task.(no special characters)no static assignmentsNo tasks have finished yet.No transitions belong to this roleNo transitions definedNot associated with any roleNote! This page is not supposed to be part of the final UI.(Note. You can only loop backwards in the process)on %task.canceled_date_pretty%Only display when task is stared?or use Attribute nameOverride default Action panel?override=%panels.overrides_action_p%; whenstarted=%panels.only_display_when_started_p%Panels for %transition_name;noquote%Place %place_name;noquote%Place: %place.place_name%
(Plaintext descriptionPlease type a name for the new roleProducing TransitionsProgrammatic AssignmentSelect the task that you want to assign the %role_name% role:set static assignmentsShow the SQL script in a <textarea> field, so you canSimple Process Wizard Step 5: Create %workflow_name;noquote%Simple Process WizardSimple Process Wizard Step 3: Loops for %workflow_name;noquote%Task: %tasks.transition_name%Task %transition_name;noquote%Task: %transition.transition_name%
(Tasks You Are Currently Working Onthat go back to a previous task. Finally, you can
set up theThe first step in defining a new process is to give it a name and an
optional description. Examples of good names are "marketing
interview", "article publication" or "expenses approval".The first step is to give athe SQL script in your browserthe task you want to loop
fromThe user performing the taskThis case is currently %case.state%(this is the only task you can possibly loop to from here)This task has been canceled byThis task was completed byThis will export the process definition as a SQL script, which you can
subsequently run on a different system, in order to recreate the process there.(This will typically take the formThis wizard will help you quickly define a simple business
process. You can add a number ofto be executed in sequence, and
you can addto your
business process.token in place %live_tokens.place_key% (%live_tokens.state%)Until we make that happen, this is the way to start a new case. Just
select a random object ... we just use it to tell the user what he's
working on.view or alter the definition%workflow_name% - %transition_name% - Task Actions%workflow_name;noquote% Cases%workflow_name;noquote% Static Assignments%workflow.num_active_cases% active cases%workflow.num_cases% cases total%workflow.pretty_name;noquote% - Process Builder%workflows.num_cases% active cases%workflows.num_unassigned_tasks% unassigned taskworkflow.workflow_nameYou canceled this task on %task.canceled_date_pretty%.You finished this task on %task.finished_date_pretty%.You haven't defined any tasks yet.
PleaseYou new business process has been created.make a copyManualManual AssignmentManual Assignmentsminutesmove upNamenameSimple ProcessAdvanced ProcessNew Advanced ProcessNo.No.No/>No\>NoNo active casesNo active tasksno assigneesNo attributesno attributesno deadlineNo old casesNo panelsNo roles definedNo tasksno tasksno tokensNo transitionsNo unassigned tasksnotnot startedNote!Notificationnow.ObjectObject Typeon the serverOn what?one task defined(optional)Optional argumentoptional descriptionOptionsOrderOutput PlacesOverride both panels?package-name/packages/Party to assignPast TasksPlacePlace namePL/SQL procPretty nameprior taskProcessprocessProcess NameProcess Name:Process StateProduced(Question)Question to askreassignReassign TaskRemoveremoveremove loopRoleRole nameRole To AssignRolesrules.SaveSelect MethodSet DeadlineSinceSort orderSpecial placestart new caseStartedStarted DateStateStaticStatic AssignmentStatic AssignmentsTaskTask donetask in the loop.Task NameTask nameTask not foundThis error can occur if a system administrator has deleted a workflow.<br>This situation should not occur during normal operations.<p>Please contact your System AdministratortasksTasks To Be Donetemplate-nameTemplate URLthe SQL scriptTimeTime EstimateTime estimateTimeoutTo DoTokensTransitionTransition PanelsTransitionsTriggerTrigger typeUnassignedUnassigned taskUnassigned TasksURLUsedValueViewWe will ask him awill be asked toWork ListWorkflowWorkflow CasesWorkflows/www/Yes/>Yes\>Yesyes/no questionYou can nowYou only have
acs-workflow-master/catalog/acs-workflow.es_ES.ISO-8859-1.xml 0000664 0000000 0000000 00000000372 14575002472 0023746 0 ustar 00root root 0000000 0000000
Part ofOn what?To Do
acs-workflow-master/catalog/acs-workflow.fr_FR.ISO-8859-1.xml 0000664 0000000 0000000 00000000374 14575002472 0023750 0 ustar 00root root 0000000 0000000
Part deEn quoi?A faire
acs-workflow-master/catalog/acs-workflow.it_IT.ISO-8859-1.xml 0000664 0000000 0000000 00000000401 14575002472 0023751 0 ustar 00root root 0000000 0000000
Parte diSu che cosa?Da fare
acs-workflow-master/catalog/acs-workflow.ja_JP.utf-8.xml 0000664 0000000 0000000 00000000255 14575002472 0023473 0 ustar 00root root 0000000 0000000
Part of
acs-workflow-master/catalog/acs-workflow.nl_NL.ISO-8859-1.xml 0000664 0000000 0000000 00000054174 14575002472 0023763 0 ustar 00root root 0000000 0000000
1 actieve toestand1 toestand totaal, bijvoorbeeld deActieActie:Type actieActiesactiesDatum activatieActieve takenToevoegentoevoegen boogVoeg gevolmachtigde toeToevoegen attribuuttoevoegen attribuutToevoegen contexttoevoegen groeptoevoegen bewakingtoevoegen loopVoeg panel toeVoeg panel toevoeg panel toetoevoegen persoonToevoegen plaatsToevoegen roltoevoegen rolToevoegen taaktoevoegen transitieAdmin workflowsBeheerderAlle atrributenAlle takenen eenarc.guard_descriptionDeel vanwijs u zelf toejezelf toewijzenGevolmachtigdentoewijzingToewijzingenAttribuutAttribuut naamattribute.nameAttributenattributendoorDoor rolannulerenannuleer taakAnnuleren(kan de boog niet toevoegen)(kan de boog niet verwijderen)(kan plaats niet verwijderen)CasusCase gestartCasussenWijzig status:wijzig naar handmatigOpmerkingenVerbruiktContextcontext.context_sleutelkopie en plaknieuwe context makenHuidige gevolmachtigdeHuidige waardeMaatwerk argumentDatatypeNiet gebruikte tokensDeadlineDeadlinesdebug casusHuidige waardeverwijderenverwijder alle casussenverwijderen boogverwijderen bewakingverwijderen plaatsverwijderen taakOmschrijvingOmschrijving:Toon: [klaat met toevoegen van loopsUitgevoerd doorUitvoeringsdatumDownloadBewerk:bewerkBewerkBewerk boogbewerken bewakingbewerken naamBewerkt panelBewerken procesnaamEffectieve gevolmachtigdenActiveerGeactivieerdexporteer procesExtreme actiesStartstartGa terugBewaak conditieKopWordt vastgehouden doorDruk op Volgende indien uTimeout bij vasthoudenHouderInitialiseer casusVoer plaats inInstructieshethet aan een bestandJournaalSleutellaatsteActuele tokensGelockedLoopLoop vanuit taakLoop naar taakloops, of u kun direct starten met de geavanceerde proces ontwerper., dus waarschijnlijk wil, zoals 'Goedgekeurd?'. Afhankelijk van het antwoord zullen we ofwel gaan naar '%loop_to_task_name%' of %loop_next_pretty%.. Dat is nauwelijks genoeg om aan te roepen een. De manier waarop het werkt is dat we de gebruiker een vraag zullen stellen waarop hij Ja of Nee moet antwoorden. Als het antwoord Ja is, dan gaan we naar dezelfde taak terug. Als het antwoord Nee is gaan we door met het afronden van het proces process—of vice versa. U mag dat bepalen.Een bewaker is een conditie waaraan voldaan moet worden om het token over die arclijn te laten verschuiven.Een loop gaat altijd terug naar eentoevoegen van een loop van '%loop_from_task_name%' terug naar zichzelfVoeg gevolmachtigde toe: %tasks.user_select_widget%%add_export_vars;noquote% Bepaal dit:Toevoegen loop van %task_name;noquote%Uitgebreide proces ontwerperAlle actieve transitiesAlle partijen zijn al aan deze taak toegevoegdtoegewezen door een andere transitie%assign_export_vars;noquote% Wijs deze toe:Toewijzen %role_name;noquote%Toewijzen %task_roles_to_assign.role_name%toewijzen van de volgende rollenToewijzen van transities aan %role.role_name;noquote%Toegewezen door de volgende transities:Toewijzingen voor %case.object_name;noquote% casusToewijzingen moeten worden uitgevoerd door %transition_name;noquote%op %task.finished_date_pretty%Attributen voor %workflow_name;noquote%Attributen moeten gedefinieerd worden door %transition_name;noquote%Business Proces AdministratieBusiness processen op dit systeemCasus: %case.object_name;noquote% (%case.state;noquote%)%case.object_name;noquote% Deadlines%case.object_name;noquote% casuswijzigen naar automatischOpmerkingen bij casus %case.object_name;noquote%Verwerken transitiesUiterste termijn is %task.deadline_pretty%het proces geheel verwijderen(Hang af van de hierboven gekozen voorwaarde)Bewerken %role_name;noquote% rolDit PL/SQL proc zal uitgevoerd worden indien %transition_name% is geactiveerd. Toe te passen voor bijvoorbeeld automatische wijzigen van een status.Iedere mogelijke gevolmachtigde is al toegewezenExporteer businessprocesga terug en definieer meer takenga terug en definieer enkele takenGa naar %tasks.loop_to_task_name% indienga naar de pagina Business Process administratiegrafische proces editor(wordt vastgehouden door taak %live_tokens.locked_task_id%)Hier is wat logica en handreikingen ter goedkeuringHier is enige informatie over de onkosten declaratie.(Indien de gebruiker antwoord wat u hier specificeert, gaat de loop terug. Indien hij een ander antwoord geeft, gaan we door naar de volgende taak.)Als u er op staat dat u maar 1 taak wilt kan dat. U kunt zelfsIndien een een meer geavanceerd proces wil, kunt ofwel hier starten en later flexibiliteit toevoegen viaIn een echte situatie zal iedere keer dat een nieuw ticket (in de ticket-tracker) of een nieuwe toepassing (voor een de taak management applicatie) is gestart, wij automatische een business process casus voor dat object zullen initialiseren.In onderstaande lijst, raak add loop aanin het proces, bijvoorbeeld van '%loop_from_task_name%' to '%loop_to_task_name%'. Of we terug gaan naar '%loop_to_task_name%' of door gaan naar %loop_next_pretty% is afhankelijk of de persoon '%loop_from_task_name%' al dan niet uitvoert. Terug loop indien het antwoord is loop.to_transition_key(maak een ja/nee vraag, bijvoorbeeld "Goedgekeurd")Handmatige toewijzing %role_name;noquote%Er zijn geen attributen gedefinieerder is geen business proces geinstalleerdgeen effectieve gevolmachtigdengeen geactiveerde transitiesEr zijn geen rollen aan deze taak toegewezen.(geen speciaal karakter)geen statische toewijzigenEr zijn nog geen taken gereed.Er zijn geen transities gekoppeld aan deze rolGeen transities gedefinieerdNiet geassocieerd met een rolAttentie! Deze pagina is niet onderdeel van de uiteindelijke UI.(Opm. u kunt alleen maar terug in het proces)op %task.canceled_date_pretty%Alleen maar tonen indien de taak blijft staan?of gebruik een Attribuut naamOverschrijven standaard actie panel?Overschrijven =%panels.overrides_action_p%; whenstarted=%panels.only_display_when_started_p%Panels voor %transition_name;noquote%Plaats %place_name;noquote%Plaats: %place.place_name% (Beschrijving in tekstType aub een naam voor de nieuwe rolAanmaken OvergangenAutomatische toewijzingenSelecteer de taak die uw wilt toewijzen aan de %role_name% rol:Zet statische toewijzingenLaat het SQL script in een <textarea>veld zien, zodat u kuntSimpel Process Wizard Stap 5: Creëer %workflow_name;noquote%Simpel Process WizardSimpel Proces Wizard Stap 3: Lussen voor %workflow_name;noquote%Taak: %tasks.transition_name%Taak %transition_name;noquote%Taak: %transition.transition_name% (De taak waaraan u momenteel werktdie teruggaat naar een voorgaande taak. Tenslotte kunt u opzetten deDe eerste stap in het definiëren van een nieuw proces is die een naam en een optionele beschrijving te geven. Voorbeelden van goede namen zijn "Marketing interview", " Publiceren artikelen" of "Goedkeuren onkosten nota".De eerste stap is om het SQL script in uw browserde taak die u wilt lussen vanafDe gebruiker die een taak uitvoertDeze casus is nu %case.state%(dit is de enige taak die u vanaf hier kunt lussen)Deze taak is geannuleerd doorDeze taak is afgerond doorDit zal de proces definitie als een SQL script exporteren. Dit script kunt achtereen volgens op een ander systeem uitvoeren zodat hier een nieuw proces kan worden gemaakt.(Dit zal standaard het formulier nemenDeze wizard helpt u met het snel definiëren van een simpel business process. U kunt meerdere zaken toevoegen alsmoet volgordelijk worden uitgevoerd, en u kunt toevoegenaan uw business process.token in plaats van %live_tokens.place_key% (%live_tokens.state%)Dit is de wijze om een nieuwe casus te starten totdat we dit mogelijk maken. Selecteer een willekeurig object... wij gebruiken het alleen om de gebruiker te vertellen waaraan hij werkt.toon of wijzig de definitie%workflow_name% - %transition_name% - Taak acties%workflow_name;noquote% Casus%workflow_name;noquote% Statische Toewijzingen%workflows.num_unassigned_tasks% niet toegewezen takenworkflow.workflow_naamU heeft deze taken gecanceld op %task.canceled_date_pretty%U heeft deze taak afgemaakt op %task.finished_date_pretty%.U heeft nog geen taken gedefinieerd. AubUw nieuwe business proces is aangemaakt.maak een kopieHandmatigHandmatige toewijzingHandmatige toewijzingenverschuif omhoogNaamnaamSimpel procesGeavanceerd procesNieuw geavanceerd procesNee,Nee,Nee/>Nee/>NeeGeen actieve casusGeen actieve taakGeen attributengeen attributengeen deadlineGeen oude casussenGeen rollen gedefinieerdGeen takengeen takengeen tokensGeen transitiesGeen niet-toegewezen takennietniet gestartOpgelet!Notificatienu.ObjectType objectop de serverOp wat?een taak gedefinieerd(optioneel)optioneel argumentoptionele beschrijvingOptiesOrdermodule-naam/modulen/Vorige taakPlaatsPlaats naamPL/SQL procvorige taakProcesprocesProces naamProces naam:Proces statusAangemaakt(Vraag)Te stellen vraagwijs opnieuw toeWijs taak opnieuw toeVerwijderverwijderverwijder loopRolRol naamToe te wijzen rolRollenregels.BewaarSelecteer methodeZet deadlineSindsSorteer volgordeSpeciale plaatsGestartDatum gestartStatusStatischStatische toewijzingStatische toewijzingenTaak Taak uitgevoerdTaak naamTaak naamTaak niet gevondenDeze fout kan voorkomen als de system administrator de workflow heeft verwijderd. <br>Deze situatie zou in normaal gebruik niet moeten voorkomen.<p>Neem contact op met de system administrator.takenUit te voeren takennaam templateTemplate URLhet SQL scriptTijdGeschatte tijdTijdTime outTakenTokensTransitieTransitiesTriggerType triggerNiet toegewezenNiet toegewezen takenNiet toegewezen takenURLGebruiktWaardeBekijkWe zullen hem vragen zal gevraagd wordenWorkflow/www/Ja/>Ja/>Jaja/nee vraagU kunt nuU heeft alleen
acs-workflow-master/catalog/acs-workflow.no_NO.ISO-8859-1.xml 0000664 0000000 0000000 00000000373 14575002472 0023761 0 ustar 00root root 0000000 0000000
Del avPå hva?Oppgaver
acs-workflow-master/catalog/acs-workflow.pl_PL.utf-8.xml 0000664 0000000 0000000 00000013547 14575002472 0023526 0 ustar 00root root 0000000 0000000
1 aktywny przypadekCzynnośćCzynnościczynnościDodajdodaj krawędźdodaj atrybutdodaj strażnikadodaj pętlędodaj paneldodaj rolędodaj przejścieZarządzaj przepływami pracyiCzęść zregułyPrzypisaniaNazwa atrybutuAtrybutyatrybutyRolaanulujPrzypadkiTyp danychTerminusuńusuń krawędźusuń strażnikausuń miejsceOpisOpis:Wyświetl: [skończyłeś dodawanie pętliEdycja:edycjaedytuj strażnikaedytuj nazwęeksportuj procesCzynności EkstremalneWarunek strażnikaNagłówekKliknij Next jeśliMiejsce WejściowePętlaPętla z zadaniaPętla do zadaniapętle,lub można zacząć od razu Advanced Process Builder.Strażnik jest warunkiem, który musi być spełniony przez token aby przejść przez ten łuk.Administracja procesami biznesowymiProcesy biznesowe W tym systemieusuń proces całkowicieIdź do %tasks.loop_to_task_name% jeśligraficzny edytor procesu(Jeśli użytkownik odpowie to, co tutaj określiłeś, nastąpi powrót. Jeśli wybierze inną odpowiedź, będzie kontynuowane następne zadanie.Jeśli chcesz tworzyć bardziej zaawansowane procesy, można rozpocząć tutaj i dodać rozszeszenia później za pomocąPowrót pętli, jeśli odpowiedź jest(utwórz pytanie na które odpowiedź będzie Tak/Nie)Uwaga! Ta strona nie ma być częścią interfejsu użytkownika końcowego.Opis tekstem jawnymktóre powracają do poprzedniego zadania. Wreszcie, można skonfigurowaćPierwszy krok to podanie(to jest jedyne zadanie do którego może być skierowana pętla)Ten kreator pomoże Ci szybko zdefiniować prosty proces biznesowy. Możesz dodać kilkaktóre będą wykonane sekwencyjnie, możesz dodaćdo Twojego
procesu biznesowego.%workflows.num_cases% aktywnych przypadków%workflows.num_unassigned_tasks% nieprzydzielony taskzrób kopięNazwanazwyProste procesyZaawansowane procesyNrNrNieBrak aktywnych przypadkówBrak starych przypadkówBrak zadańniePowiadomieniaObjektNa co?opcjonalnie opisuKolejnośćMiejsce WyjścioweMiejsceProcesNazwa ProcesuNazwa Procesu:Pytanieusuń pętlęRolaRoleprzydziału.rozpocznij nowy przypadekPrzypisania StatyczneZadaniezadańSzacowany czasDo zrobieniaPrzejściePanele PrzejściaPrzejścieWyzwalaczNieprzypisaneUżywanyPrzypadki przepływu pracyPrzepływy pracyTak
acs-workflow-master/catalog/acs-workflow.pt_BR.ISO-8859-1.xml 0000664 0000000 0000000 00000000370 14575002472 0023754 0 ustar 00root root 0000000 0000000
Parte deEm?A fazer
acs-workflow-master/catalog/acs-workflow.ru_RU.utf-8.xml 0000775 0000000 0000000 00000000342 14575002472 0023544 0 ustar 00root root 0000000 0000000
Входит вСпиÑок дел
acs-workflow-master/catalog/acs-workflow.tr_TR.utf-8.xml 0000664 0000000 0000000 00000000372 14575002472 0023542 0 ustar 00root root 0000000 0000000
Part ofHangi konuda?Yapılacak
acs-workflow-master/catalog/acs-workflow.zh_CN.utf-8.xml 0000664 0000000 0000000 00000000370 14575002472 0023507 0 ustar 00root root 0000000 0000000
部分在哪里?待办事项
acs-workflow-master/catalog/acs-workflow.zh_TW.utf-8.xml 0000664 0000000 0000000 00000000322 14575002472 0023536 0 ustar 00root root 0000000 0000000
åœ¨å“ªé‚Šä»£è¾¦äº‹é …
acs-workflow-master/sql/ 0000775 0000000 0000000 00000000000 14575002472 0015572 5 ustar 00root root 0000000 0000000 acs-workflow-master/sql/oracle/ 0000775 0000000 0000000 00000000000 14575002472 0017037 5 ustar 00root root 0000000 0000000 acs-workflow-master/sql/oracle/acs-workflow-create.sql 0000664 0000000 0000000 00000000615 14575002472 0023441 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/acs-workflow-create.sql
--
-- Calls the other SQL files to create the data models and PL/SQL packages.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
@@ wf-core-create
@@ workflow-case-package
@@ workflow-package
@@ wf-callback-package
/* We create two sample processes */
@@ sample-expenses-create
@@ sample-article-create
acs-workflow-master/sql/oracle/acs-workflow-drop.sql 0000664 0000000 0000000 00000000454 14575002472 0023143 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/acs-workflow-drop.sql
--
-- Drops the data model and the PL/SQL packages.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
@@ jobs-kill
@@ wf-core-drop
drop package wf_callback;
drop package workflow;
drop package workflow_case;
acs-workflow-master/sql/oracle/load-workflow.sql 0000664 0000000 0000000 00000011206 14575002472 0022347 0 ustar 00root root 0000000 0000000 alter session set sql_trace = false
set autotrace off
set timing off
create or replace function
my_random
return integer
is
begin
return dbms_random.random/power(2,32)+0.5;
end my_random;
/
show errors
create or replace procedure
push_task_ahead(
task_id integer,
state in varchar2,
user_id in integer,
workflow_key in varchar2,
transition_key in varchar2
)
is
v_journal_id integer;
v_value char(1);
begin
if state = 'enabled' then
v_journal_id := workflow_case.task_action(
task_id => push_task_ahead.task_id,
action => 'start',
action_ip => '1.1.1.1',
user_id => push_task_ahead.user_id
);
else
/* State must be started */
if my_random < 0.02 then
v_journal_id := workflow_case.task_action(
task_id => push_task_ahead.task_id,
action => 'cancel',
action_ip => '1.1.1.1',
user_id => push_task_ahead.user_id
);
else
v_journal_id := workflow_case.begin_task_action(
task_id => push_task_ahead.task_id,
action => 'finish',
action_ip => '1.1.1.1',
user_id => push_task_ahead.user_id
);
for attr_rec in (select a.attribute_name, datatype
from wf_transition_attribute_map m, acs_attributes a
where workflow_key = push_task_ahead.workflow_key
and transition_key = push_task_ahead.transition_key
and a.attribute_id = m.attribute_id)
loop
/* We only know how to handle boolean attributes ... but that's the only thing we have right now, so ... */
if attr_rec.datatype = 'boolean' then
if my_random < 0.5 then
v_value := 't';
else
v_value := 'f';
end if;
workflow_case.set_attribute_value(
journal_id => v_journal_id,
attribute_name => attr_rec.attribute_name,
value => v_value
);
end if;
end loop;
workflow_case.end_task_action(
journal_id => v_journal_id,
action => 'finish',
task_id => push_task_ahead.task_id
);
end if;
end if;
end;
/
show errors
declare
v_object_id integer;
v_workflow_key varchar2(100);
v_count integer;
v_num_cases integer;
v_party_id integer;
v_case_id integer;
v_task_id integer;
v_user_id integer;
v_num_tasks integer;
v_state varchar2(100);
v_transition_key varchar2(100);
begin
v_num_cases := 100;
dbms_random.initialize(943820482);
/* Create a shit-load of cases */
for v_count in 1 .. v_num_cases
loop
select object_id into v_object_id from acs_objects where rownum = 1;
select workflow_key into v_workflow_key from wf_workflows where rownum = 1;
v_case_id := workflow_case.new(
workflow_key => v_workflow_key,
object_id => v_object_id
);
for trans_rec in (select transition_key from wf_transitions where workflow_key = v_workflow_key) loop
for party_rec in (select party_id from parties sample(50)) loop
workflow_case.add_manual_assignment(
case_id => v_case_id,
transition_key => trans_rec.transition_key,
party_id => party_rec.party_id
);
end loop;
end loop;
workflow_case.start_case(
case_id => v_case_id
);
end loop;
/* Move 85% of the cases all the way to finished */
for case_rec in (select case_id from wf_cases sample (85))
loop
loop
select decode(count(*), 0, 0, 1) into v_num_tasks from wf_user_tasks;
exit when v_num_tasks = 0;
if my_random < 0.005 then
workflow_case.cancel(
case_id => case_rec.case_id
);
end if;
select task_id, state, user_id, workflow_key, transition_key
into v_task_id, v_state, v_user_id, v_workflow_key, v_transition_key
from wf_user_tasks
where case_id = case_rec.case_id
and rownum = 1;
push_task_ahead(
task_id => v_task_id,
state => v_state,
user_id => v_user_id,
workflow_key => v_workflow_key,
transition_key => v_transition_key
);
end loop;
end loop;
/* Fire transitions at random */
for v_count in 1 .. round(v_num_cases * 0.15 * 3)
loop
select decode(count(*), 0, 0, 1) into v_num_tasks from wf_user_tasks;
exit when v_num_tasks = 0;
select task_id, state, user_id, workflow_key, transition_key
into v_task_id, v_state, v_user_id, v_workflow_key, v_transition_key
from wf_user_tasks
where rownum = 1;
push_task_ahead(
task_id => v_task_id,
state => v_state,
user_id => v_user_id,
workflow_key => v_workflow_key,
transition_key => v_transition_key
);
end loop;
end;
/
show errors
acs-workflow-master/sql/oracle/sample-article-create.sql 0000664 0000000 0000000 00000017260 14575002472 0023731 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/sample-article-create.sql
--
-- Creates a sample article-authoring workflow to play with
--
-- @author Kevin Scaldeferri (kevin@theory.caltech.edu)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
/* This table will hold one row for each case using this workflow. */
create table wf_article_cases (
case_id integer primary key
constraint wf_article_cases_case_fk
references wf_cases on delete cascade
);
declare
v_workflow_key wf_workflows.workflow_key%TYPE;
v_attribute_id acs_attributes.attribute_id%TYPE;
begin
v_workflow_key := workflow.create_workflow(
workflow_key => 'article_wf',
pretty_name => 'Article Publication',
pretty_plural => 'Article Publications',
description => 'Workflow for managing the publication of an article',
table_name => 'wf_article_cases'
);
/*****
* Places
*****/
workflow.add_place(
workflow_key => 'article_wf',
place_key => 'start',
place_name => 'Start place',
sort_order => 1
);
workflow.add_place(
workflow_key => 'article_wf',
place_key => 'to_be_written',
place_name => 'Needs to be written',
sort_order => 2
);
workflow.add_place(
workflow_key => 'article_wf',
place_key => 'to_be_reviewed',
place_name => 'Needs review',
sort_order => 3
);
workflow.add_place(
workflow_key => 'article_wf',
place_key => 'to_be_published',
place_name => 'Ready to go to press',
sort_order => 4
);
workflow.add_place(
workflow_key => 'article_wf',
place_key => 'end',
place_name => 'End place',
sort_order => 5
);
/*****
* Roles
*****/
workflow.add_role(
workflow_key => 'article_wf',
role_key => 'author',
role_name => 'Author',
sort_order => 1
);
workflow.add_role(
workflow_key => 'article_wf',
role_key => 'editor',
role_name => 'Editor',
sort_order => 2
);
/*****
* Transitions
*****/
workflow.add_transition(
workflow_key => 'article_wf',
transition_key => 'specify',
transition_name => 'Describe task and assign author',
role_key => 'editor',
sort_order => 1,
trigger_type => 'user'
);
workflow.add_transition(
workflow_key => 'article_wf',
transition_key => 'write',
transition_name => 'Write article',
role_key => 'author',
sort_order => 2,
trigger_type => 'user'
);
workflow.add_transition(
workflow_key => 'article_wf',
transition_key => 'review',
transition_name => 'Review article',
role_key => 'editor',
sort_order => 3,
trigger_type => 'user'
);
workflow.add_transition(
workflow_key => 'article_wf',
transition_key => 'publish',
transition_name => 'Publish article',
sort_order => 4,
trigger_type => 'automatic'
);
/*****
* Arcs
*****/
workflow.add_arc(
workflow_key => 'article_wf',
from_place_key => 'start',
to_transition_key => 'specify'
);
workflow.add_arc(
workflow_key => 'article_wf',
from_transition_key => 'specify',
to_place_key => 'to_be_written'
);
workflow.add_arc(
workflow_key => 'article_wf',
from_place_key => 'to_be_written',
to_transition_key => 'write'
);
workflow.add_arc(
workflow_key => 'article_wf',
from_transition_key => 'write',
to_place_key => 'to_be_reviewed'
);
workflow.add_arc(
workflow_key => 'article_wf',
from_place_key => 'to_be_reviewed',
to_transition_key => 'review'
);
workflow.add_arc(
workflow_key => 'article_wf',
from_transition_key => 'review',
to_place_key => 'to_be_published',
guard_callback => 'wf_callback.guard_attribute_true',
guard_custom_arg => 'reviewer_ok',
guard_description => 'Reviewer approved article'
);
workflow.add_arc(
workflow_key => 'article_wf',
from_transition_key => 'review',
to_place_key => 'to_be_written',
guard_callback => '#',
guard_description => 'Reviewer did not approve article'
);
workflow.add_arc(
workflow_key => 'article_wf',
from_place_key => 'to_be_published',
to_transition_key => 'publish'
);
workflow.add_arc(
workflow_key => 'article_wf',
from_transition_key => 'publish',
to_place_key => 'end'
);
/*****
* Attributes
*****/
v_attribute_id := workflow.create_attribute(
workflow_key => 'article_wf',
attribute_name => 'reviewer_ok',
datatype => 'boolean',
pretty_name => 'Reviewer Approval',
default_value => 'f'
);
workflow.add_trans_attribute_map(
workflow_key => 'article_wf',
transition_key => 'review',
attribute_name => 'reviewer_ok',
sort_order => 1
);
/*****
* Assignment
*****/
workflow.add_trans_role_assign_map(
workflow_key => 'article_wf',
transition_key => 'specify',
assign_role_key => 'author'
);
end;
/
show errors
/* Context stuff */
insert into wf_context_transition_info (
context_key,
workflow_key,
transition_key,
hold_timeout_callback,
hold_timeout_custom_arg
) values (
'default',
'article_wf',
'specify',
'wf_callback.time_sysdate_plus_x',
1/24
);
commit;
create or replace package wf_article_callback
is
procedure notification(
task_id in number,
custom_arg in varchar2,
party_to in integer,
party_from in integer,
subject in varchar2,
body in varchar2
);
end wf_article_callback;
/
show errors
create or replace package body wf_article_callback
is
procedure notification(
task_id in number,
custom_arg in varchar2,
party_to in integer,
party_from in integer,
subject in varchar2,
body in varchar2
)
is
v_deadline_pretty varchar2(400);
v_object_name varchar2(4000);
v_transition_name wf_transitions.transition_name%TYPE;
v_name varchar2(1000);
v_subject varchar2(100);
v_body varchar2(4000);
v_request_id integer;
begin
select to_char(ta.deadline,'Mon fmDDfm, YYYY HH24:MI:SS'),
acs_object.name(c.object_id),
tr.transition_name
into v_deadline_pretty,
v_object_name,
v_transition_name
from wf_tasks ta, wf_transitions tr, wf_cases c
where ta.task_id = notification.task_id
and c.case_id = ta.case_id
and tr.workflow_key = c.workflow_key
and tr.transition_key = ta.transition_key;
v_subject := 'Assignment: '||v_transition_name||' '||v_object_name;
v_body := 'Dear '||acs_object.name(party_to)||'
'||'
Today, you have been assigned to a task.
'||'
Task : '||v_transition_name||'
Object : '||v_object_name||'
';
if v_deadline_pretty != '' then
v_body := v_body ||'Deadline: '||v_deadline_pretty||'
';
end if;
v_request_id := acs_mail_nt.post_request (
party_from => party_from,
party_to => party_to,
subject => v_subject,
message => v_body
);
end notification;
end wf_article_callback;
/
show errors
update wf_context_transition_info
set notification_callback = 'wf_article_callback.notification'
where workflow_key = 'article_wf'
and context_key = 'default'
and transition_key = 'specify';
commit;
acs-workflow-master/sql/oracle/sample-article-drop.sql 0000664 0000000 0000000 00000000625 14575002472 0023427 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/sample-article-drop.sql
--
-- Drops the article-authoring workflow.
--
-- @author Kevin Scaldeferri (kevin@theory.caltech.edu)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
begin
workflow.delete_cases(workflow_key => 'article_wf');
end;
/
show errors;
drop table wf_article_cases;
begin
workflow.drop_workflow(workflow_key => 'article_wf');
end;
/
show errors;
acs-workflow-master/sql/oracle/sample-expenses-create.sql 0000664 0000000 0000000 00000025751 14575002472 0024144 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/sample-expenses-create.sql
--
-- Creates an expenses workflow to play with.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
/* This table will hold one row for each case using this workflow. */
create table wf_expenses_cases (
case_id integer primary key
constraint wf_expenses_cases_case_fk
references wf_cases on delete cascade
);
declare
v_workflow_key wf_workflows.workflow_key%TYPE;
v_attribute_id acs_attributes.attribute_id%TYPE;
begin
v_workflow_key := workflow.create_workflow(
workflow_key => 'expenses_wf',
pretty_name => 'Expense Authorization',
pretty_plural => 'Expense authorizations',
description => 'Workflow for authorizing employee''s expenses on the company''s behalf',
table_name => 'wf_expenses_cases'
);
/*****
* Places
*****/
workflow.add_place(
workflow_key => 'expenses_wf',
place_key => 'start',
place_name => 'Start place',
sort_order => 1
);
workflow.add_place(
workflow_key => 'expenses_wf',
place_key => 'assignments_done',
place_name => 'Tasks have been assigned',
sort_order => 2
);
workflow.add_place(
workflow_key => 'expenses_wf',
place_key => 'supervisor_to_approve',
place_name => 'Supervisor is to approve',
sort_order => 3
);
workflow.add_place(
workflow_key => 'expenses_wf',
place_key => 'other_to_approve',
place_name => 'Other is to approve',
sort_order => 4
);
workflow.add_place(
workflow_key => 'expenses_wf',
place_key => 'supervisor_approved',
place_name => 'Supervisor has approved',
sort_order => 5
);
workflow.add_place(
workflow_key => 'expenses_wf',
place_key => 'other_approved',
place_name => 'Other has approved',
sort_order => 6
);
workflow.add_place(
workflow_key => 'expenses_wf',
place_key => 'ready_to_buy',
place_name => 'Both have approved',
sort_order => 7
);
workflow.add_place(
workflow_key => 'expenses_wf',
place_key => 'end',
place_name => 'End place',
sort_order => 8
);
/*****
* Roles
*****/
workflow.add_role(
workflow_key => 'expenses_wf',
role_key => 'assignor',
role_name => 'Assignor',
sort_order => 1
);
workflow.add_role(
workflow_key => 'expenses_wf',
role_key => 'supervisor',
role_name => 'Supervisor',
sort_order => 2
);
workflow.add_role(
workflow_key => 'expenses_wf',
role_key => 'other',
role_name => 'Other approver',
sort_order => 3
);
workflow.add_role(
workflow_key => 'expenses_wf',
role_key => 'requestor',
role_name => 'Requestor',
sort_order => 4
);
/*****
* Transitions
*****/
workflow.add_transition(
workflow_key => 'expenses_wf',
transition_key => 'assign',
transition_name => 'Assign users to approval',
role_key => 'assignor',
sort_order => 1,
trigger_type => 'user'
);
workflow.add_transition(
workflow_key => 'expenses_wf',
transition_key => 'and_split',
transition_name => 'Parallel approval by supervisor and other',
sort_order => 2,
trigger_type => 'automatic'
);
workflow.add_transition(
workflow_key => 'expenses_wf',
transition_key => 'supervisor_approval',
transition_name => 'Approve (Supervisor)',
role_key => 'supervisor',
sort_order => 3,
trigger_type => 'user'
);
workflow.add_transition(
workflow_key => 'expenses_wf',
transition_key => 'other_approval',
transition_name => 'Approve (Other)',
role_key => 'other',
sort_order => 4,
trigger_type => 'user'
);
workflow.add_transition(
workflow_key => 'expenses_wf',
transition_key => 'and_join',
transition_name => 'Re-synchronization from approval by supervisor and other',
sort_order => 5,
trigger_type => 'automatic'
);
workflow.add_transition(
workflow_key => 'expenses_wf',
transition_key => 'buy',
transition_name => 'Buy stuff',
role_key => 'requestor',
sort_order => 6,
trigger_type => 'user'
);
/*****
* Arcs
*****/
workflow.add_arc(
workflow_key => 'expenses_wf',
from_place_key => 'start',
to_transition_key => 'assign'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_transition_key => 'assign',
to_place_key => 'assignments_done'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_place_key => 'assignments_done',
to_transition_key => 'and_split'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_transition_key => 'and_split',
to_place_key => 'supervisor_to_approve'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_transition_key => 'and_split',
to_place_key => 'other_to_approve'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_place_key => 'supervisor_to_approve',
to_transition_key => 'supervisor_approval'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_transition_key => 'supervisor_approval',
to_place_key => 'supervisor_approved'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_place_key => 'other_to_approve',
to_transition_key => 'other_approval'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_transition_key => 'other_approval',
to_place_key => 'other_approved'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_place_key => 'supervisor_approved',
to_transition_key => 'and_join'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_place_key => 'other_approved',
to_transition_key => 'and_join'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_transition_key => 'and_join',
to_place_key => 'ready_to_buy',
guard_callback => 'wf_expenses.guard_both_approved_p',
guard_description => 'Both Supervisor and the Other approver approved'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_transition_key => 'and_join',
to_place_key => 'end',
guard_callback => '#',
guard_description => 'Either Supervisor or the Other approver did not approve'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_place_key => 'ready_to_buy',
to_transition_key => 'buy'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_transition_key => 'buy',
to_place_key => 'end'
);
/*****
* Attributes
*****/
v_attribute_id := workflow.create_attribute(
workflow_key => 'expenses_wf',
attribute_name => 'supervisor_ok',
datatype => 'boolean',
pretty_name => 'Supervisor Approval',
default_value => 'f',
sort_order => 1
);
workflow.add_trans_attribute_map(
workflow_key => 'expenses_wf',
transition_key => 'supervisor_approval',
attribute_name => 'supervisor_ok',
sort_order => 1
);
v_attribute_id := workflow.create_attribute(
workflow_key => 'expenses_wf',
attribute_name => 'other_ok',
datatype => 'boolean',
pretty_name => 'Other Approval',
default_value => 'f',
sort_order => 2
);
workflow.add_trans_attribute_map(
workflow_key => 'expenses_wf',
transition_key => 'other_approval',
attribute_name => 'other_ok',
sort_order => 1
);
/*****
* Assignment
*****/
workflow.add_trans_role_assign_map(
workflow_key => 'expenses_wf',
transition_key => 'assign',
assign_role_key => 'supervisor'
);
workflow.add_trans_role_assign_map(
workflow_key => 'expenses_wf',
transition_key => 'assign',
assign_role_key => 'other'
);
end;
/
show errors
/* Context stuff */
insert into wf_context_transition_info (
context_key, workflow_key, transition_key, estimated_minutes
) values (
'default', 'expenses_wf', 'assign', 5
);
insert into wf_context_transition_info (
context_key, workflow_key, transition_key, hold_timeout_callback, hold_timeout_custom_arg, estimated_minutes
) values (
'default', 'expenses_wf', 'supervisor_approval', 'wf_callback.time_sysdate_plus_x', 1/24, 15
);
insert into wf_context_transition_info (
context_key, workflow_key, transition_key, estimated_minutes
) values (
'default', 'expenses_wf', 'other_approval', 15
);
insert into wf_context_transition_info (
context_key, workflow_key, transition_key, estimated_minutes
) values (
'default', 'expenses_wf', 'buy', 30
);
insert into wf_context_task_panels (
context_key, workflow_key, transition_key, sort_order, header, template_url
) values (
'default', 'expenses_wf', 'supervisor_approval', 1, 'Claim Info', 'sample/expenses-claim-info'
);
insert into wf_context_task_panels (
context_key, workflow_key, transition_key, sort_order, header, template_url
) values (
'default', 'expenses_wf', 'supervisor_approval', 2, 'Logic and Aids', 'sample/expenses-approval-aids'
);
insert into wf_context_task_panels (
context_key, workflow_key, transition_key, sort_order, header, template_url
) values (
'default', 'expenses_wf', 'other_approval', 1, 'Claim Info', 'sample/expenses-claim-info'
);
insert into wf_context_task_panels (
context_key, workflow_key, transition_key, sort_order, header, template_url
) values (
'default', 'expenses_wf', 'other_approval', 2, 'Logic and Aids', 'sample/expenses-approval-aids'
);
commit;
/* Callbacks for the workflow */
create or replace package wf_expenses
is
function guard_both_approved_p (
case_id in number,
workflow_key in varchar2,
transition_key in varchar2,
place_key in varchar2,
direction_in varchar2,
custom_arg in varchar2
)
return char;
end wf_expenses;
/
show errors;
create or replace package body wf_expenses
is
function guard_both_approved_p (
case_id in number,
workflow_key in varchar2,
transition_key in varchar2,
place_key in varchar2,
direction_in varchar2,
custom_arg in varchar2
)
return char
is
v_other_ok_p char(1);
v_supervisor_ok_p char(1);
begin
v_other_ok_p := workflow_case.get_attribute_value(
case_id => guard_both_approved_p.case_id,
attribute_name => 'other_ok'
);
if v_other_ok_p = 'f' then
return 'f';
end if;
v_supervisor_ok_p := workflow_case.get_attribute_value(
case_id => guard_both_approved_p.case_id,
attribute_name => 'supervisor_ok'
);
return v_supervisor_ok_p;
end guard_both_approved_p;
end wf_expenses;
/
show errors;
acs-workflow-master/sql/oracle/sample-expenses-drop.sql 0000664 0000000 0000000 00000000576 14575002472 0023643 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/sample-expenses-drop.sql
--
-- Drops the expenses workflow.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
begin
workflow.delete_cases(workflow_key => 'expenses_wf');
end;
/
show errors;
drop table wf_expenses_cases;
begin
workflow.drop_workflow(workflow_key => 'expenses_wf');
end;
/
show errors;
acs-workflow-master/sql/oracle/test/ 0000775 0000000 0000000 00000000000 14575002472 0020016 5 ustar 00root root 0000000 0000000 acs-workflow-master/sql/oracle/test/workflow-case-package-test.sql 0000664 0000000 0000000 00000027533 14575002472 0025702 0 ustar 00root root 0000000 0000000 set serveroutput on size 1000000 format wrapped
-- requires the utPLSQL system
--
-- modify this line to suit your needs
--
-- exec utplsql.setdir('/web/lars-dev2/packages/acs-kernel/sql');
exec utplsql.autocompile (false);
create or replace package ut#workflow_case
as
procedure setup;
procedure teardown;
procedure run;
end ut#workflow_case;
/
show errors
create or replace package body ut#workflow_case
as
procedure setup
is
wf_count number;
begin
teardown;
dbms_output.put_line('Setting up...');
/* We assume that the sample-expenses workflow is loaded and unchanged from the original */
select decode(count(*),0,0,1) into wf_count from wf_workflows where workflow_key = 'expenses_wf';
if wf_count = 0 then
raise_application_error(-20000, 'The sample-expenses workflow must be loaded (and unchanged from the original)');
end if;
utplsql.setpkg('workflow_case');
utplsql.addtest('run');
end;
procedure teardown
is
begin
dbms_output.put_line('Tearing down...');
end;
procedure run
is
v_workflow_key wf_workflows.workflow_key%TYPE;
v_object_id acs_objects.object_id%TYPE;
v_case_id wf_cases.case_id%TYPE;
v_count number;
v_task_id number;
v_journal_id number;
v_user_id number;
v_state varchar2(100);
begin
v_workflow_key := 'expenses_wf';
dbms_output.put_line('Running test...');
/* Pick out a random object ... we just hope there is one somewhere */
select object_id into v_object_id from acs_objects where rownum = 1;
dbms_output.put_line('. new case');
v_case_id := workflow_case.new(
workflow_key => v_workflow_key,
context_key => 'default',
object_id => v_object_id
);
dbms_output.put_line('. manual assignments');
/* we need a random user_id */
select user_id into v_user_id
from users
where rownum = 1;
workflow_case.add_manual_assignment (
case_id => v_case_id,
transition_key => 'assign',
party_id => v_user_id
);
workflow_case.add_manual_assignment (
case_id => v_case_id,
transition_key => 'supervisor_approval',
party_id => v_user_id
);
workflow_case.add_manual_assignment (
case_id => v_case_id,
transition_key => 'other_approval',
party_id => v_user_id
);
workflow_case.add_manual_assignment (
case_id => v_case_id,
transition_key => 'buy',
party_id => v_user_id
);
dbms_output.put_line('. start case');
workflow_case.start_case(
case_id => v_case_id
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id
and transition_key = 'assign'
and state = 'enabled';
utassert.eq(
msg_in => 'We should have exactly one ''assign'' task enabled',
check_this_in => 1,
against_this_in => v_count
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id;
utassert.eq(
msg_in => 'The ''assign'' task should be the only task there is for this case yet.',
check_this_in => 1,
against_this_in => v_count
);
/* Get that task_id */
select task_id into v_task_id
from wf_tasks
where case_id = v_case_id
and transition_key = 'assign'
and state = 'enabled';
dbms_output.put_line('. start task ''assign''');
v_journal_id := workflow_case.begin_task_action(
task_id => v_task_id,
action => 'start',
action_ip => '0.0.0.0',
user_id => v_user_id,
msg => 'regression-test: started task ''assign'''
);
workflow_case.end_task_action(
journal_id => v_journal_id,
action => 'start',
task_id => v_task_id
);
select state into v_state
from wf_tasks
where task_id = v_task_id;
utassert.eq(
msg_in => 'The ''assign'' task should be in state ''started''.',
check_this_in => 'started',
against_this_in => v_state
);
dbms_output.put_line('. cancel task ''assign''');
v_journal_id := workflow_case.begin_task_action(
task_id => v_task_id,
action => 'cancel',
action_ip => '0.0.0.0',
user_id => v_user_id,
msg => 'regression-test: canceled task ''assign'''
);
workflow_case.end_task_action(
journal_id => v_journal_id,
action => 'cancel',
task_id => v_task_id
);
select state into v_state
from wf_tasks
where task_id = v_task_id;
utassert.eq(
msg_in => 'The ''assign'' task should be in state ''canceled''.',
check_this_in => 'canceled',
against_this_in => v_state
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id
and transition_key = 'assign'
and state = 'enabled';
utassert.eq(
msg_in => 'We should have exactly one ''assign'' task enabled',
check_this_in => 1,
against_this_in => v_count
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id;
utassert.eq(
msg_in => 'There should be exactly two tasks for this case, one enabled and one canceled.',
check_this_in => 2,
against_this_in => v_count
);
dbms_output.put_line('. finish task ''assign''');
/* Get that task_id for the 'assign' task */
select task_id into v_task_id
from wf_tasks
where case_id = v_case_id
and transition_key = 'assign'
and state = 'enabled';
v_journal_id := workflow_case.begin_task_action(
task_id => v_task_id,
action => 'finish',
action_ip => '0.0.0.0',
user_id => v_user_id,
msg => 'regression-test: finished task ''assign'''
);
workflow_case.end_task_action(
journal_id => v_journal_id,
action => 'finish',
task_id => v_task_id
);
select state into v_state
from wf_tasks
where task_id = v_task_id;
utassert.eq(
msg_in => 'The ''assign'' task should be in state ''finished''.',
check_this_in => 'finished',
against_this_in => v_state
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id
and transition_key = 'supervisor_approval'
and state = 'enabled';
utassert.eq(
msg_in => 'We should have exactly one ''supervisor_approval'' task enabled',
check_this_in => 1,
against_this_in => v_count
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id
and transition_key = 'other_approval'
and state = 'enabled';
utassert.eq(
msg_in => 'We should have exactly one ''other_approval'' task enabled',
check_this_in => 1,
against_this_in => v_count
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id;
utassert.eq(
msg_in => 'There should be exactly five tasks for this case, one canceled, two finished, and two enabled.',
check_this_in => 5,
against_this_in => v_count
);
dbms_output.put_line('. finish task ''supervisor_approval'' without starting it first (saying okay)');
/* Get the task_id for the supervisor_approval task */
select task_id into v_task_id
from wf_tasks
where case_id = v_case_id
and transition_key = 'supervisor_approval'
and state = 'enabled';
v_journal_id := workflow_case.begin_task_action(
task_id => v_task_id,
action => 'finish',
action_ip => '0.0.0.0',
user_id => v_user_id,
msg => 'regression-test: finished task ''supervisor_approval'''
);
workflow_case.set_attribute_value(
journal_id => v_journal_id,
attribute_name => 'supervisor_ok',
value => 't'
);
workflow_case.end_task_action(
journal_id => v_journal_id,
action => 'finish',
task_id => v_task_id
);
select state into v_state
from wf_tasks
where task_id = v_task_id;
utassert.eq(
msg_in => 'The ''supervisor_approval'' task should be in state ''finished''.',
check_this_in => 'finished',
against_this_in => v_state
);
dbms_output.put_line('. finish task ''other_approval'' without starting it first (saying okay)');
/* Get the task_id for the other_approval task */
select task_id into v_task_id
from wf_tasks
where case_id = v_case_id
and transition_key = 'other_approval'
and state = 'enabled';
v_journal_id := workflow_case.begin_task_action(
task_id => v_task_id,
action => 'finish',
action_ip => '0.0.0.0',
user_id => v_user_id,
msg => 'regression-test: finished task ''other_approval'''
);
workflow_case.set_attribute_value(
journal_id => v_journal_id,
attribute_name => 'other_ok',
value => 't'
);
workflow_case.end_task_action(
journal_id => v_journal_id,
action => 'finish',
task_id => v_task_id
);
select state into v_state
from wf_tasks
where task_id = v_task_id;
utassert.eq(
msg_in => 'The ''other_approval'' task should be in state ''finished''.',
check_this_in => 'finished',
against_this_in => v_state
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id
and state = 'enabled';
utassert.eq(
msg_in => 'We should have exactly one task enabled',
check_this_in => 1,
against_this_in => v_count
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id
and transition_key = 'buy'
and state = 'enabled';
utassert.eq(
msg_in => 'We should have the ''buy'' task enabled',
check_this_in => 1,
against_this_in => v_count
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id;
utassert.eq(
msg_in => 'There should be exactly seven tasks for this case, one canceled, six finished, and one enabled.',
check_this_in => 7,
against_this_in => v_count
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id
and state = 'finished';
utassert.eq(
msg_in => 'There should be exactly five finished tasks',
check_this_in => 5,
against_this_in => v_count
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id
and state = 'canceled';
utassert.eq(
msg_in => 'There should be exactly one canceled task',
check_this_in => 1,
against_this_in => v_count
);
dbms_output.put_line('. finish task ''buy''');
/* Get that task_id for the 'buy' task */
select task_id into v_task_id
from wf_tasks
where case_id = v_case_id
and transition_key = 'buy'
and state = 'enabled';
v_journal_id := workflow_case.begin_task_action(
task_id => v_task_id,
action => 'finish',
action_ip => '0.0.0.0',
user_id => v_user_id,
msg => 'regression-test: finished task ''buy'''
);
workflow_case.end_task_action(
journal_id => v_journal_id,
action => 'finish',
task_id => v_task_id
);
select state into v_state
from wf_tasks
where task_id = v_task_id;
utassert.eq(
msg_in => 'The ''buy'' task should be in state ''finished''.',
check_this_in => 'finished',
against_this_in => v_state
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id;
utassert.eq(
msg_in => 'There should be exactly seven tasks for this case, one canceled, six finished, and one enabled.',
check_this_in => 7,
against_this_in => v_count
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id
and state = 'finished';
utassert.eq(
msg_in => 'There should be exactly six finished tasks',
check_this_in => 6,
against_this_in => v_count
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id
and state = 'canceled';
utassert.eq(
msg_in => 'There should be exactly one canceled task',
check_this_in => 1,
against_this_in => v_count
);
select state into v_state
from wf_cases
where case_id = v_case_id;
utassert.eq(
msg_in => 'The case should be finished',
check_this_in => 'finished',
against_this_in => v_state
);
utresult.show;
end;
end ut#workflow_case;
/
show errors
exec utplsql.test('workflow_case'); acs-workflow-master/sql/oracle/upgrade-4.0-4.0.1.sql 0000664 0000000 0000000 00000027137 14575002472 0022156 0 ustar 00root root 0000000 0000000 -- Recreating almost all foreign key constraints in order to add "on delete cascade"
-- wf_workflows
alter table wf_workflows drop constraint wf_workflows_workflow_key_fk;
alter table wf_workflows add (
constraint wf_workflows_workflow_key_fk
foreign key(workflow_key) references acs_object_types(object_type) on delete cascade
);
-- wf_places
alter table wf_places drop constraint wf_place_workflow_fk;
alter table wf_places add (
constraint wf_place_workflow_fk
foreign key(workflow_key) references wf_workflows(workflow_key) on delete cascade
);
-- wf_transitions
alter table wf_transitions drop constraint wf_transition_workflow_fk;
alter table wf_transitions add (
constraint wf_transition_workflow_fk
foreign key(workflow_key) references wf_workflows(workflow_key) on delete cascade
);
-- wf_arcs
alter table wf_arcs drop constraint wf_ts_arc_workflow_fk;
alter table wf_arcs add (
constraint wf_ts_arc_workflow_fk
foreign key(workflow_key) references wf_workflows(workflow_key) on delete cascade
);
alter table wf_arcs drop constraint wf_arc_transition_fk;
alter table wf_arcs add (
constraint wf_arc_transition_fk
foreign key(workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
alter table wf_arcs drop constraint wf_arc_place_fk;
alter table wf_arcs add (
constraint wf_arc_place_fk
foreign key(workflow_key, place_key) references wf_places(workflow_key, place_key) on delete cascade
);
create index wf_arcs_wf_key_trans_key_idx on wf_arcs(workflow_key, transition_key);
create index wf_arcs_wf_key_place_key_idx on wf_arcs(workflow_key, place_key);
-- wf_attribute_info
alter table wf_attribute_info add (
constraint wf_attribute_info_attribute_pk primary key(attribute_id)
);
alter table wf_attribute_info drop constraint wf_attribute_info_attribute_fk;
alter table wf_attribute_info add (
constraint wf_attribute_info_attribute_fk
foreign key(attribute_id) references acs_attributes(attribute_id) on delete cascade
);
-- wf_transition_attribute_map
alter table wf_transition_attribute_map drop constraint wf_trans_attr_map_workflow_fk;
alter table wf_transition_attribute_map add (
constraint wf_trans_attr_map_workflow_fk
foreign key(workflow_key) references wf_workflows(workflow_key) on delete cascade
);
alter table wf_transition_attribute_map drop constraint wf_trans_attr_map_trans_fk;
alter table wf_transition_attribute_map add (
constraint wf_trans_attr_map_trans_fk
foreign key(workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
-- wf_transition_assignment_map
alter table wf_transition_assignment_map drop constraint wf_trans_asgn_map_workflow_fk;
alter table wf_transition_assignment_map add (
constraint wf_trans_asgn_map_workflow_fk
foreign key(workflow_key) references wf_workflows(workflow_key) on delete cascade
);
alter table wf_transition_assignment_map drop constraint wf_trans_asgn_map_trans_fk;
alter table wf_transition_assignment_map add (
constraint wf_trans_asgn_map_trans_fk
foreign key(workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
alter table wf_transition_assignment_map drop constraint wf_tr_asgn_map_asgn_trans_fk;
alter table wf_transition_assignment_map add (
constraint wf_tr_asgn_map_asgn_trans_fk
foreign key(workflow_key, assign_transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
create index wf_trans_asgn_map_wf_trans_idx on wf_transition_assignment_map(workflow_key, transition_key);
create index wf_trans_asgn_map_wf_as_tr_idx on wf_transition_assignment_map(workflow_key, assign_transition_key);
-- wf_context_transition_info
alter table wf_context_transition_info drop constraint wf_context_trans_trans_fk;
alter table wf_context_transition_info add (
constraint wf_context_trans_trans_fk
foreign key(workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
create index wf_ctx_trans_wf_trans_idx on wf_context_transition_info(workflow_key, transition_key);
-- wf_context_assignments
alter table wf_context_assignments drop constraint wf_context_assign_context_fk;
alter table wf_context_assignments add (
constraint wf_context_assign_context_fk
foreign key(context_key) references wf_contexts(context_key) on delete cascade
);
alter table wf_context_assignments drop constraint wf_context_assign_workflow_fk;
alter table wf_context_assignments add (
constraint wf_context_assign_workflow_fk
foreign key(workflow_key) references wf_workflows(workflow_key) on delete cascade
);
alter table wf_context_assignments drop constraint wf_context_assign_party_fk;
alter table wf_context_assignments add (
constraint wf_context_assign_party_fk
foreign key(party_id) references parties(party_id) on delete cascade
);
alter table wf_context_assignments drop constraint wf_context_assign_trans_fk;
alter table wf_context_assignments add (
constraint wf_context_assign_trans_fk
foreign key(workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
create index wf_ctx_assg_workflow_trans_idx on wf_context_assignments(workflow_key, transition_key);
-- wf_cases
alter table wf_cases drop constraint wf_cases_acs_object_fk;
alter table wf_cases add (
constraint wf_cases_acs_object_fk
foreign key(case_id) references acs_objects(object_id) on delete cascade
);
alter table wf_cases drop constraint wf_cases_workflow_fk;
alter table wf_cases add (
constraint wf_cases_workflow_fk
foreign key(workflow_key) references wf_workflows(workflow_key) on delete cascade
);
alter table wf_cases drop constraint wf_cases_context_fk;
alter table wf_cases add (
constraint wf_cases_context_fk
foreign key(context_key) references wf_contexts(context_key) on delete cascade
);
alter table wf_cases drop constraint wf_cases_object_fk;
alter table wf_cases add (
constraint wf_cases_object_fk
foreign key(object_id) references acs_objects(object_id) on delete cascade
);
create index wf_cases_workflow_key_idx on wf_cases(workflow_key);
create index wf_cases_context_key_idx on wf_cases(context_key);
create index wf_cases_object_id_idx on wf_cases(object_id);
-- wf_case_assignments
alter table wf_case_assignments drop constraint wf_case_assign_fk;
alter table wf_case_assignments add (
constraint wf_case_assign_fk
foreign key(case_id) references wf_cases(case_id) on delete cascade
);
alter table wf_case_assignments drop constraint wf_case_assign_party_fk;
alter table wf_case_assignments add (
constraint wf_case_assign_party_fk
foreign key(party_id) references parties(party_id) on delete cascade
);
alter table wf_case_assignments drop constraint wf_case_assign_trans_fk;
alter table wf_case_assignments add (
constraint wf_case_assign_trans_fk
foreign key(workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
create index wf_case_assgn_party_idx on wf_case_assignments(party_id);
-- wf_case_deadlines
alter table wf_case_deadlines drop constraint wf_case_deadline_fk;
alter table wf_case_deadlines add (
constraint wf_case_deadline_fk
foreign key(case_id) references wf_cases(case_id) on delete cascade
);
alter table wf_case_deadlines drop constraint wf_case_deadline_trans_fk;
alter table wf_case_deadlines add (
constraint wf_case_deadline_trans_fk
foreign key(workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
-- wf_tasks
alter table wf_tasks drop constraint wf_task_case_fk;
alter table wf_tasks add (
constraint wf_task_case_fk
foreign key(case_id) references wf_cases(case_id) on delete cascade
);
alter table wf_tasks drop constraint wf_task_holding_user_fk;
alter table wf_tasks add (
constraint wf_task_holding_user_fk
foreign key(holding_user) references users(user_id) on delete cascade
);
create index wf_tasks_case_id_idx on wf_tasks(case_id);
create index wf_tasks_holding_user_idx on wf_tasks(holding_user);
-- wf_task_assignments
alter table wf_task_assignments drop constraint wf_task_assign_task_fk;
alter table wf_task_assignments add (
constraint wf_task_assign_task_fk
foreign key(task_id) references wf_tasks(task_id) on delete cascade
);
alter table wf_task_assignments drop constraint wf_task_party_fk;
alter table wf_task_assignments add (
constraint wf_task_party_fk
foreign key(party_id) references parties(party_id) on delete cascade
);
create index wf_task_asgn_party_id_idx on wf_task_assignments(party_id);
-- wf_tokens
alter table wf_tokens drop constraint wf_token_workflow_instance_fk;
alter table wf_tokens add (
constraint wf_token_workflow_instance_fk
foreign key(case_id) references wf_cases(case_id) on delete cascade
);
create index wf_tokens_case_id_idx on wf_tokens(case_id);
-- wf_attribute_value_audit
alter table wf_attribute_value_audit drop constraint wf_attr_val_audit_case_fk;
alter table wf_attribute_value_audit add (
constraint wf_attr_val_audit_case_fk
foreign key(case_id) references wf_cases(case_id) on delete cascade
);
alter table wf_attribute_value_audit drop constraint wf_attr_val_audit_attr_fk;
alter table wf_attribute_value_audit add (
constraint wf_attr_val_audit_attr_fk
foreign key(attribute_id) references acs_attributes(attribute_id) on delete cascade
);
create index wf_attr_val_aud_attr_id_idx on wf_attribute_value_audit(attribute_id);
-- Added a column to wf_tasks
alter table wf_tasks add (estimated_minutes integer);
-- We've added the column estimated_minutes to this view.
create or replace view wf_enabled_transitions as
select c.case_id,
t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.context_key,
t.enable_callback,
t.enable_custom_arg,
t.fire_callback,
t.fire_custom_arg,
t.assignment_callback,
t.assignment_custom_arg,
t.time_callback,
t.time_custom_arg,
t.deadline_callback,
t.deadline_custom_arg,
t.deadline_attribute_name,
t.hold_timeout_callback,
t.hold_timeout_custom_arg,
t.estimated_minutes
from wf_transition_info t,
wf_cases c
where t.workflow_key = c.workflow_key
and t.context_key = c.context_key
and c.state = 'active'
and not exists
(select tp.place_key
from wf_transition_places tp
where tp.transition_key = t.transition_key
and tp.workflow_key = t.workflow_key
and tp.direction = 'in'
and not exists
(select tk.token_id
from wf_tokens tk
where tk.place_key = tp.place_key
and tk.case_id = c.case_id
and tk.state = 'free'
)
);
-- We've added the column workflow_key to this view
create or replace view wf_user_tasks as
select distinct ta.task_id,
ta.case_id,
ta.workflow_key,
ta.transition_key,
tr.transition_name,
ta.enabled_date,
ta.started_date,
u.user_id,
ta.state,
ta.holding_user,
ta.hold_timeout,
ta.deadline,
ta.estimated_minutes
from wf_tasks ta,
wf_task_assignments tasgn,
wf_cases c,
wf_transition_info tr,
party_approved_member_map m,
users u
where ta.state in ( 'enabled','started')
and c.case_id = ta.case_id
and c.state = 'active'
and tr.transition_key = ta.transition_key
and tr.trigger_type = 'user'
and tr.context_key = c.context_key
and tasgn.task_id = ta.task_id
and m.party_id = tasgn.party_id
and u.user_id = m.member_id;
acs-workflow-master/sql/oracle/upgrade-4.1.1-4.3.sql 0000664 0000000 0000000 00000040254 14575002472 0022155 0 ustar 00root root 0000000 0000000 /*
* We've added support for roles, which is an intermediate step between
* transitions and assignments. A role is a relationship to a process, e.g.,
* an editor, publisher, submitter, fixer, doctor, manager, etc.
* A task is performed by a role, but one role may have many tasks to perform.
* The idea is that when you reassign a role, it affects all the tasks that role
* has been assigned to.
*
* For the upgrade, we simply create one role per transtiion, and change
* all the other tables correspondingly. This will execute exactly equivalent
* to the way it would have without the roles refactoring.
*
* We've also added other minor things, such as task instructions and gotten rid
* of wf_attribute_info.
*/
/*
* Table wf_roles:
* Added.
*/
create table wf_roles (
role_key varchar2(100),
workflow_key varchar2(100)
constraint wf_roles_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
role_name varchar2(100)
constraint wf_role_role_name_nn
not null,
-- so we can display roles in some logical order --
sort_order integer
constraint wf_roles_order_ck
check (sort_order > 0),
-- table constraints --
constraint wf_role_pk
primary key (workflow_key, role_key),
constraint wf_roles_wf_key_role_name_un
unique (workflow_key, role_name)
);
comment on table wf_roles is '
A process has certain roles associated with it, such as "submitter",
"reviewer", "editor", "claimant", etc. For each transition, then, you
specify what role is to perform that task. Thus, two or more tasks can be
performed by one and the same role, so that when the role is reassigned,
it reflects assignments of both tasks. Users and parties are then assigned
to roles instead of directly to tasks.
';
/*
* Now populate the roles table:
* We just create a role per transition, then hook them up
*/
insert into wf_roles
(workflow_key,
role_key,
role_name,
sort_order)
select workflow_key, transition_key, transition_name, sort_order
from wf_transitions;
/*
* Table wf_transitions:
* Added column role_key.
* Added foreign key constraint wf_transition_role_fk.
*/
alter table wf_transitions add (
role_key varchar2(100)
);
alter table wf_transitions add (
constraint wf_transition_role_fk
foreign key (workflow_key,role_key) references wf_roles(workflow_key,role_key)
/* We don't do on delete cascade here, because that would mean that
* when a role is deleted, the transitions associated with that role would be deleted, too */
);
/* Now populate the new column corresponding to the roles we just created:
* Since there's a one-to-one role per transition, and the have the same keys,
* we just set role_key = transition_key
*/
update wf_transitions
set role_key = transition_key;
/*
* Table wf_transition_role_assign_map:
* Added.
* This replaces wf_transtiion_assign_map, since transitions now assign
* roles instead of other transitions.
*/
create table wf_transition_role_assign_map (
workflow_key varchar2(100)
constraint wf_role_asgn_map_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
transition_key varchar2(100),
assign_role_key varchar2(100),
-- table constraints --
constraint wf_role_asgn_map_pk
primary key (workflow_key, transition_key, assign_role_key),
constraint wf_role_asgn_map_trans_fk
foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key)
on delete cascade,
constraint wf_tr_role_asgn_map_asgn_fk
foreign key (workflow_key, assign_role_key) references wf_roles(workflow_key, role_key)
on delete cascade
);
create index wf_role_asgn_map_wf_trans_idx on wf_transition_role_assign_map(workflow_key, transition_key);
create index wf_role_asgn_map_wf_as_tr_idx on wf_transition_role_assign_map(workflow_key, assign_role_key);
comment on table wf_transition_role_assign_map is '
When part of the output of one task is to assign users to a role,
specify that this is the case by inserting a row here.
';
comment on column wf_transition_role_assign_map.transition_key is '
transition_key is the assigning transition.
';
comment on column wf_transition_role_assign_map.assign_role_key is '
assign_role_key is the role being assigned a user to.
';
/* Populate new wf_transition_role_assign_map with the rows from
* wf_transition_assignment_map. Since role_key map one-to-one with transition_keys
* in this upgrade, that's pretty straight-forward.
*/
insert into wf_transition_role_assign_map
(workflow_key,
transition_key,
assign_role_key)
select workflow_key,
transition_key,
assign_transition_key
from wf_transition_assignment_map;
/*
* Table wf_transition_assignment_map:
* Dropped.
* This table is no longer releavnt, since transitions don't assign other
* transitions, they assign roles.
*/
drop table wf_transition_assignment_map;
/*
* Table wf_attribute_info:
* Dropped.
* This table was a hang-over from earlier versions and is no longer necessary.
*/
drop table wf_attribute_info;
/*
* Table wf_context_role_info:
* Added.
*/
create table wf_context_role_info (
context_key varchar2(100)
constraint wf_context_role_context_fk
references wf_contexts(context_key)
on delete cascade,
workflow_key varchar2(100)
constraint wf_context_role_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
role_key varchar2(100),
/*
* Callback to programatically assign a role.
* Must call wordflow_case.*_role_assignment to make the assignments.
* Will be called when a transition for that role becomes enabled
* signature: (role_key in varchar2, custom_arg in varchar2)
*/
assignment_callback varchar2(100),
assignment_custom_arg varchar2(4000),
-- table constraints --
constraint wf_context_role_role_fk
foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key)
on delete cascade,
constraint wf_context_role_info_pk
primary key (context_key, workflow_key, role_key)
);
comment on table wf_context_role_info is '
This table holds context-dependent info for roles, currently only the assignment callback
';
/* Populate by a straight copy from wf_context_transition_info */
insert into wf_context_role_info
(context_key,
workflow_key,
role_key,
assignment_callback,
assignment_custom_arg)
select context_key,
workflow_key,
transition_key,
assignment_callback,
assignment_custom_arg
from wf_context_transition_info
where assignment_callback is not null
or assignment_custom_arg is not null;
/*
* Table wf_context_transition_info:
* Added column 'instructions'.
*/
alter table wf_context_transition_info add (
instructions varchar2(4000)
);
/* Removed columns assignment_callback/custom_arg. */
alter table wf_context_transition_info
drop column assignment_callback;
alter table wf_context_transition_info
drop column assignment_custom_arg;
/* Added on delete cascade to columns workflow_key and .context_key */
alter table wf_context_transition_info
drop constraint wf_context_trans_context_fk;
alter table wf_context_transition_info
add constraint wf_context_trans_context_fk
foreign key (context_key) references wf_contexts (context_key);
alter table wf_context_transition_info
drop constraint wf_context_trans_workflow_fk;
alter table wf_context_transition_info
add constraint wf_context_trans_workflow_fk
foreign key (workflow_key) references wf_workflows (workflow_key);
/*
* Table wf_context_workflow_info:
* Added.
*/
create table wf_context_workflow_info (
context_key varchar2(100)
constraint wf_context_wf_context_fk
references wf_contexts
on delete cascade,
workflow_key varchar2(100)
constraint wf_context_wf_workflow_fk
references wf_workflows
on delete cascade,
/* The principal is the user/party that sends out email assignment notifications
* And receives email when a task becomes unassigned (for more than x minutes?)
*/
principal_party integer
constraint wf_context_wf_principal_fk
references parties
on delete set null,
-- table constraints --
constraint wf_context_workflow_pk
primary key (context_key, workflow_key)
);
/* Insert someone for all existing processes. Hopefully this will be the administrator user. */
insert into wf_context_workflow_info
(context_key,
workflow_key,
principal_party)
select 'default', workflow_key, (select min(party_id) from parties)
from wf_workflows;
/*
* Table wf_context_task_panels:
* Added columns overrides_action_p and only_display_when_started_p
* Renamed column sort_key to sort_order for consistency
*/
alter table wf_context_task_panels add (
/* Display this panel in place of the action panel */
overrides_action_p char(1) default 'f'
constraint wf_context_panels_ovrd_p_ck
check (overrides_action_p in ('t','f')),
/* Display this panel only when the task has been started (and not finished) */
only_display_when_started_p char(1) default 'f'
constraint wf_context_panels_display_p_ck
check (only_display_when_started_p in ('t','f')),
sort_order integer
);
/* Copy over the existing sort_key to the new sort_order */
update wf_context_task_panels
set sort_order = sort_key;
/* Change the primary key */
alter table wf_context_task_panels drop constraint wf_context_panels_pk;
alter table wf_context_task_panels add
constraint wf_context_panels_pk
primary key (context_key, workflow_key, transition_key, sort_order);
/* Drop old sort_key column */
alter table wf_context_task_panels drop column sort_key;
alter table wf_context_task_panels add constraint wf_context_sort_order_nn
check (sort_order is not null);
/*
* Table wf_context_assignments
* Replaced transition_key with role_key
*/
alter table wf_context_assignments add (
role_key varchar2(100),
constraint wf_context_assign_role_fk
foreign key (workflow_key, role_key) references wf_roles (workflow_key, role_key)
on delete cascade
);
alter table wf_context_assignments drop constraint wf_context_assign_trans_fk;
update wf_context_assignments
set role_key = transition_key;
alter table wf_context_assignments drop constraint wf_context_assign_pk;
alter table wf_context_assignments add constraint wf_context_assign_pk
primary key (context_key, workflow_key, role_key, party_id);
alter table wf_context_assignments drop column transition_key;
/*
* Table wf_case_assignments:
* Changed transition_key to role_key
*/
alter table wf_case_assignments add (
role_key varchar2(100),
constraint wf_case_assign_role_fk
foreign key (workflow_key, role_key) references wf_roles (workflow_key, role_key)
on delete cascade
);
update wf_case_assignments
set role_key = transition_key;
alter table wf_case_assignments drop constraint wf_case_assign_pk;
alter table wf_case_assignments add
constraint wf_case_assign_pk
primary key (case_id, role_key, party_id);
alter table wf_case_assignments drop constraint wf_case_assign_trans_fk;
alter table wf_case_assignments drop column transition_key;
/*
* View wf_transition_contexts:
* Added column role_key.
*/
create or replace view wf_transition_contexts as
select t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.role_key,
c.context_key,
c.context_name
from wf_transitions t, wf_contexts c;
/*
* View wf_transition_info:
* Added columns role_key and instructions.
* Removed columns assignment_callback/custom_arg.
*/
create or replace view wf_transition_info as
select t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.context_key,
t.role_key,
ct.estimated_minutes,
ct.instructions,
ct.enable_callback,
ct.enable_custom_arg,
ct.fire_callback,
ct.fire_custom_arg,
ct.time_callback,
ct.time_custom_arg,
ct.deadline_callback,
ct.deadline_custom_arg,
ct.deadline_attribute_name,
ct.hold_timeout_callback,
ct.hold_timeout_custom_arg,
ct.notification_callback,
ct.notification_custom_arg,
ct.unassigned_callback,
ct.unassigned_custom_arg
from wf_transition_contexts t, wf_context_transition_info ct
where ct.workflow_key (+) = t.workflow_key
and ct.transition_key (+) = t.transition_key
and ct.context_key (+) = t.context_key;
/*
* View wf_role_info:
* Added.
*/
create or replace view wf_role_info as
select r.role_key,
r.role_name,
r.workflow_key,
c.context_key,
cr.assignment_callback,
cr.assignment_custom_arg
from wf_roles r, wf_contexts c, wf_context_role_info cr
where cr.workflow_key (+) = r.workflow_key
and cr.role_key (+) = r.role_key
and cr.context_key = c.context_key;
/*
* View wf_enabled_transitions:
* Added columns role_key and instructions.
* Removed columns assignment_callback/custom_arg.
*/
create or replace view wf_enabled_transitions as
select c.case_id,
t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.context_key,
t.role_key,
t.enable_callback,
t.enable_custom_arg,
t.fire_callback,
t.fire_custom_arg,
t.time_callback,
t.time_custom_arg,
t.deadline_callback,
t.deadline_custom_arg,
t.deadline_attribute_name,
t.hold_timeout_callback,
t.hold_timeout_custom_arg,
t.notification_callback,
t.notification_custom_arg,
t.estimated_minutes,
t.instructions,
t.unassigned_callback,
t.unassigned_custom_arg
from wf_transition_info t,
wf_cases c
where t.workflow_key = c.workflow_key
and t.context_key = c.context_key
and c.state = 'active'
and not exists
(select tp.place_key
from wf_transition_places tp
where tp.transition_key = t.transition_key
and tp.workflow_key = t.workflow_key
and tp.direction = 'in'
and not exists
(select tk.token_id
from wf_tokens tk
where tk.place_key = tp.place_key
and tk.case_id = c.case_id
and tk.state = 'free'
)
);
/*
* View wf_user_tasks:
* Added column instructions
* Added "and tr.workflow_key = ta.workflow_key" to where clause
* (looks like a bug)
*/
create or replace view wf_user_tasks as
select distinct ta.task_id,
ta.case_id,
ta.workflow_key,
ta.transition_key,
tr.transition_name,
tr.instructions,
ta.enabled_date,
ta.started_date,
u.user_id,
ta.state,
ta.holding_user,
ta.hold_timeout,
ta.deadline,
ta.estimated_minutes
from wf_tasks ta,
wf_task_assignments tasgn,
wf_cases c,
wf_transition_info tr,
party_approved_member_map m,
users u
where ta.state in ( 'enabled','started')
and c.case_id = ta.case_id
and c.state = 'active'
and tr.transition_key = ta.transition_key
and tr.workflow_key = ta.workflow_key
and tr.trigger_type = 'user'
and tr.context_key = c.context_key
and tasgn.task_id = ta.task_id
and m.party_id = tasgn.party_id
and u.user_id = m.member_id;
@@workflow-package.sql
@@workflow-case-package-head.sql
@@workflow-case-package-body.sql
acs-workflow-master/sql/oracle/upgrade/ 0000775 0000000 0000000 00000000000 14575002472 0020466 5 ustar 00root root 0000000 0000000 acs-workflow-master/sql/oracle/upgrade/upgrade-4.0-4.0.1.sql 0000664 0000000 0000000 00000027137 14575002472 0023605 0 ustar 00root root 0000000 0000000 -- Recreating almost all foreign key constraints in order to add "on delete cascade"
-- wf_workflows
alter table wf_workflows drop constraint wf_workflows_workflow_key_fk;
alter table wf_workflows add (
constraint wf_workflows_workflow_key_fk
foreign key(workflow_key) references acs_object_types(object_type) on delete cascade
);
-- wf_places
alter table wf_places drop constraint wf_place_workflow_fk;
alter table wf_places add (
constraint wf_place_workflow_fk
foreign key(workflow_key) references wf_workflows(workflow_key) on delete cascade
);
-- wf_transitions
alter table wf_transitions drop constraint wf_transition_workflow_fk;
alter table wf_transitions add (
constraint wf_transition_workflow_fk
foreign key(workflow_key) references wf_workflows(workflow_key) on delete cascade
);
-- wf_arcs
alter table wf_arcs drop constraint wf_ts_arc_workflow_fk;
alter table wf_arcs add (
constraint wf_ts_arc_workflow_fk
foreign key(workflow_key) references wf_workflows(workflow_key) on delete cascade
);
alter table wf_arcs drop constraint wf_arc_transition_fk;
alter table wf_arcs add (
constraint wf_arc_transition_fk
foreign key(workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
alter table wf_arcs drop constraint wf_arc_place_fk;
alter table wf_arcs add (
constraint wf_arc_place_fk
foreign key(workflow_key, place_key) references wf_places(workflow_key, place_key) on delete cascade
);
create index wf_arcs_wf_key_trans_key_idx on wf_arcs(workflow_key, transition_key);
create index wf_arcs_wf_key_place_key_idx on wf_arcs(workflow_key, place_key);
-- wf_attribute_info
alter table wf_attribute_info add (
constraint wf_attribute_info_attribute_pk primary key(attribute_id)
);
alter table wf_attribute_info drop constraint wf_attribute_info_attribute_fk;
alter table wf_attribute_info add (
constraint wf_attribute_info_attribute_fk
foreign key(attribute_id) references acs_attributes(attribute_id) on delete cascade
);
-- wf_transition_attribute_map
alter table wf_transition_attribute_map drop constraint wf_trans_attr_map_workflow_fk;
alter table wf_transition_attribute_map add (
constraint wf_trans_attr_map_workflow_fk
foreign key(workflow_key) references wf_workflows(workflow_key) on delete cascade
);
alter table wf_transition_attribute_map drop constraint wf_trans_attr_map_trans_fk;
alter table wf_transition_attribute_map add (
constraint wf_trans_attr_map_trans_fk
foreign key(workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
-- wf_transition_assignment_map
alter table wf_transition_assignment_map drop constraint wf_trans_asgn_map_workflow_fk;
alter table wf_transition_assignment_map add (
constraint wf_trans_asgn_map_workflow_fk
foreign key(workflow_key) references wf_workflows(workflow_key) on delete cascade
);
alter table wf_transition_assignment_map drop constraint wf_trans_asgn_map_trans_fk;
alter table wf_transition_assignment_map add (
constraint wf_trans_asgn_map_trans_fk
foreign key(workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
alter table wf_transition_assignment_map drop constraint wf_tr_asgn_map_asgn_trans_fk;
alter table wf_transition_assignment_map add (
constraint wf_tr_asgn_map_asgn_trans_fk
foreign key(workflow_key, assign_transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
create index wf_trans_asgn_map_wf_trans_idx on wf_transition_assignment_map(workflow_key, transition_key);
create index wf_trans_asgn_map_wf_as_tr_idx on wf_transition_assignment_map(workflow_key, assign_transition_key);
-- wf_context_transition_info
alter table wf_context_transition_info drop constraint wf_context_trans_trans_fk;
alter table wf_context_transition_info add (
constraint wf_context_trans_trans_fk
foreign key(workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
create index wf_ctx_trans_wf_trans_idx on wf_context_transition_info(workflow_key, transition_key);
-- wf_context_assignments
alter table wf_context_assignments drop constraint wf_context_assign_context_fk;
alter table wf_context_assignments add (
constraint wf_context_assign_context_fk
foreign key(context_key) references wf_contexts(context_key) on delete cascade
);
alter table wf_context_assignments drop constraint wf_context_assign_workflow_fk;
alter table wf_context_assignments add (
constraint wf_context_assign_workflow_fk
foreign key(workflow_key) references wf_workflows(workflow_key) on delete cascade
);
alter table wf_context_assignments drop constraint wf_context_assign_party_fk;
alter table wf_context_assignments add (
constraint wf_context_assign_party_fk
foreign key(party_id) references parties(party_id) on delete cascade
);
alter table wf_context_assignments drop constraint wf_context_assign_trans_fk;
alter table wf_context_assignments add (
constraint wf_context_assign_trans_fk
foreign key(workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
create index wf_ctx_assg_workflow_trans_idx on wf_context_assignments(workflow_key, transition_key);
-- wf_cases
alter table wf_cases drop constraint wf_cases_acs_object_fk;
alter table wf_cases add (
constraint wf_cases_acs_object_fk
foreign key(case_id) references acs_objects(object_id) on delete cascade
);
alter table wf_cases drop constraint wf_cases_workflow_fk;
alter table wf_cases add (
constraint wf_cases_workflow_fk
foreign key(workflow_key) references wf_workflows(workflow_key) on delete cascade
);
alter table wf_cases drop constraint wf_cases_context_fk;
alter table wf_cases add (
constraint wf_cases_context_fk
foreign key(context_key) references wf_contexts(context_key) on delete cascade
);
alter table wf_cases drop constraint wf_cases_object_fk;
alter table wf_cases add (
constraint wf_cases_object_fk
foreign key(object_id) references acs_objects(object_id) on delete cascade
);
create index wf_cases_workflow_key_idx on wf_cases(workflow_key);
create index wf_cases_context_key_idx on wf_cases(context_key);
create index wf_cases_object_id_idx on wf_cases(object_id);
-- wf_case_assignments
alter table wf_case_assignments drop constraint wf_case_assign_fk;
alter table wf_case_assignments add (
constraint wf_case_assign_fk
foreign key(case_id) references wf_cases(case_id) on delete cascade
);
alter table wf_case_assignments drop constraint wf_case_assign_party_fk;
alter table wf_case_assignments add (
constraint wf_case_assign_party_fk
foreign key(party_id) references parties(party_id) on delete cascade
);
alter table wf_case_assignments drop constraint wf_case_assign_trans_fk;
alter table wf_case_assignments add (
constraint wf_case_assign_trans_fk
foreign key(workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
create index wf_case_assgn_party_idx on wf_case_assignments(party_id);
-- wf_case_deadlines
alter table wf_case_deadlines drop constraint wf_case_deadline_fk;
alter table wf_case_deadlines add (
constraint wf_case_deadline_fk
foreign key(case_id) references wf_cases(case_id) on delete cascade
);
alter table wf_case_deadlines drop constraint wf_case_deadline_trans_fk;
alter table wf_case_deadlines add (
constraint wf_case_deadline_trans_fk
foreign key(workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
-- wf_tasks
alter table wf_tasks drop constraint wf_task_case_fk;
alter table wf_tasks add (
constraint wf_task_case_fk
foreign key(case_id) references wf_cases(case_id) on delete cascade
);
alter table wf_tasks drop constraint wf_task_holding_user_fk;
alter table wf_tasks add (
constraint wf_task_holding_user_fk
foreign key(holding_user) references users(user_id) on delete cascade
);
create index wf_tasks_case_id_idx on wf_tasks(case_id);
create index wf_tasks_holding_user_idx on wf_tasks(holding_user);
-- wf_task_assignments
alter table wf_task_assignments drop constraint wf_task_assign_task_fk;
alter table wf_task_assignments add (
constraint wf_task_assign_task_fk
foreign key(task_id) references wf_tasks(task_id) on delete cascade
);
alter table wf_task_assignments drop constraint wf_task_party_fk;
alter table wf_task_assignments add (
constraint wf_task_party_fk
foreign key(party_id) references parties(party_id) on delete cascade
);
create index wf_task_asgn_party_id_idx on wf_task_assignments(party_id);
-- wf_tokens
alter table wf_tokens drop constraint wf_token_workflow_instance_fk;
alter table wf_tokens add (
constraint wf_token_workflow_instance_fk
foreign key(case_id) references wf_cases(case_id) on delete cascade
);
create index wf_tokens_case_id_idx on wf_tokens(case_id);
-- wf_attribute_value_audit
alter table wf_attribute_value_audit drop constraint wf_attr_val_audit_case_fk;
alter table wf_attribute_value_audit add (
constraint wf_attr_val_audit_case_fk
foreign key(case_id) references wf_cases(case_id) on delete cascade
);
alter table wf_attribute_value_audit drop constraint wf_attr_val_audit_attr_fk;
alter table wf_attribute_value_audit add (
constraint wf_attr_val_audit_attr_fk
foreign key(attribute_id) references acs_attributes(attribute_id) on delete cascade
);
create index wf_attr_val_aud_attr_id_idx on wf_attribute_value_audit(attribute_id);
-- Added a column to wf_tasks
alter table wf_tasks add (estimated_minutes integer);
-- We've added the column estimated_minutes to this view.
create or replace view wf_enabled_transitions as
select c.case_id,
t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.context_key,
t.enable_callback,
t.enable_custom_arg,
t.fire_callback,
t.fire_custom_arg,
t.assignment_callback,
t.assignment_custom_arg,
t.time_callback,
t.time_custom_arg,
t.deadline_callback,
t.deadline_custom_arg,
t.deadline_attribute_name,
t.hold_timeout_callback,
t.hold_timeout_custom_arg,
t.estimated_minutes
from wf_transition_info t,
wf_cases c
where t.workflow_key = c.workflow_key
and t.context_key = c.context_key
and c.state = 'active'
and not exists
(select tp.place_key
from wf_transition_places tp
where tp.transition_key = t.transition_key
and tp.workflow_key = t.workflow_key
and tp.direction = 'in'
and not exists
(select tk.token_id
from wf_tokens tk
where tk.place_key = tp.place_key
and tk.case_id = c.case_id
and tk.state = 'free'
)
);
-- We've added the column workflow_key to this view
create or replace view wf_user_tasks as
select distinct ta.task_id,
ta.case_id,
ta.workflow_key,
ta.transition_key,
tr.transition_name,
ta.enabled_date,
ta.started_date,
u.user_id,
ta.state,
ta.holding_user,
ta.hold_timeout,
ta.deadline,
ta.estimated_minutes
from wf_tasks ta,
wf_task_assignments tasgn,
wf_cases c,
wf_transition_info tr,
party_approved_member_map m,
users u
where ta.state in ( 'enabled','started')
and c.case_id = ta.case_id
and c.state = 'active'
and tr.transition_key = ta.transition_key
and tr.trigger_type = 'user'
and tr.context_key = c.context_key
and tasgn.task_id = ta.task_id
and m.party_id = tasgn.party_id
and u.user_id = m.member_id;
acs-workflow-master/sql/oracle/upgrade/upgrade-4.0.1-4.1b.sql 0000664 0000000 0000000 00000012323 14575002472 0023737 0 ustar 00root root 0000000 0000000 /*
* Panels callbacks have changed.
*
* Instead of a Tcl callback (sick idea, we knew that all along),
* we now store a list of URLs of templates to include.
*/
/* Drop the old column */
alter table wf_context_transition_info drop column panels_callback_tcl;
/* Add the new table instead */
create table wf_context_task_panels (
context_key varchar2(100) not null
constraint wf_context_panels_context_fk
references wf_contexts(context_key)
on delete cascade,
workflow_key varchar2(100) not null
constraint wf_context_panels_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
transition_key varchar2(100) not null,
sort_key integer not null,
header varchar2(200) not null,
template_url varchar2(500) not null,
/* table constraints */
constraint wf_context_panels_trans_fk
foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key)
on delete cascade,
constraint wf_context_panels_pk
primary key (context_key, workflow_key, transition_key, sort_key)
);
create index wf_ctx_panl_workflow_trans_idx on wf_context_task_panels(workflow_key, transition_key);
comment on table wf_context_task_panels is '
Holds information about the panels to be displayed on the task page.
';
/*
* Added a Notification callback.
*
*/
alter table wf_context_transition_info add (
/*
* Notification callback
* Will be called when a notification is sent i.e., when a transition is enabled,
* or assignment changes.
* signature: (task_id in number,
* custom_arg in varchar2,
* party_to in integer,
* party_from in out integer,
* subject in out varchar2,
* body in out varchar2)
*/
notification_callback varchar2(100),
notification_custom_arg varchar2(4000)
);
/*
* Enhanced comment on wf_cases.object_id
*
*/
comment on column wf_cases.object_id is '
A case is itself an acs_object, but moreover, a case will always be about some
other acs_object. E.g. for ticket-tracker, the case_id will refer to an instance of
the ticket-tracker-workflow, while the object_id will refer to the ticket itself.
It is possible to have multiple cases around the same object.
';
/*
* Added unassigned callback
*/
alter table wf_context_transition_info add (
/*
* Unassigned callback
* Will be called whenever a task becomes unassigned
* Signature: (case_id in number, transition_key in varchar2, custom_arg in varchar2)
*/
unassigned_callback varchar2(100),
unassigned_custom_arg varchar2(4000)
);
/*
* Added access privilege
*/
alter table wf_context_transition_info add (
/* name of the privilege we should check before allowing access
* to task information.
*/
access_privilege varchar2(100)
);
/* panels_callback_tcl, notification_callback and unassigned_callback
* affect this view.
*/
create or replace view wf_transition_info as
select t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.context_key,
ct.estimated_minutes,
ct.enable_callback,
ct.enable_custom_arg,
ct.fire_callback,
ct.fire_custom_arg,
ct.assignment_callback,
ct.assignment_custom_arg,
ct.time_callback,
ct.time_custom_arg,
ct.deadline_callback,
ct.deadline_custom_arg,
ct.deadline_attribute_name,
ct.hold_timeout_callback,
ct.hold_timeout_custom_arg,
ct.notification_callback,
ct.notification_custom_arg,
ct.unassigned_callback,
ct.unassigned_custom_arg,
ct.access_privilege
from wf_transition_contexts t, wf_context_transition_info ct
where ct.workflow_key (+) = t.workflow_key
and ct.transition_key (+) = t.transition_key
and ct.context_key (+) = t.context_key;
/* Notifications and unassigned affect this */
create or replace view wf_enabled_transitions as
select c.case_id,
t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.context_key,
t.enable_callback,
t.enable_custom_arg,
t.fire_callback,
t.fire_custom_arg,
t.assignment_callback,
t.assignment_custom_arg,
t.time_callback,
t.time_custom_arg,
t.deadline_callback,
t.deadline_custom_arg,
t.deadline_attribute_name,
t.hold_timeout_callback,
t.hold_timeout_custom_arg,
t.notification_callback,
t.notification_custom_arg,
t.unassigned_callback,
t.unassigned_custom_arg,
t.estimated_minutes,
t.access_privilege
from wf_transition_info t,
wf_cases c
where t.workflow_key = c.workflow_key
and t.context_key = c.context_key
and c.state = 'active'
and not exists
(select tp.place_key
from wf_transition_places tp
where tp.transition_key = t.transition_key
and tp.workflow_key = t.workflow_key
and tp.direction = 'in'
and not exists
(select tk.token_id
from wf_tokens tk
where tk.place_key = tp.place_key
and tk.case_id = c.case_id
and tk.state = 'free'
)
);
acs-workflow-master/sql/oracle/upgrade/upgrade-4.1b-4.3.sql 0000664 0000000 0000000 00000040740 14575002472 0023607 0 ustar 00root root 0000000 0000000 /*
* We've added support for roles, which is an intermediate step between
* transitions and assignments. A role is a relationship to a process, e.g.,
* an editor, publisher, submitter, fixer, doctor, manager, etc.
* A task is performed by a role, but one role may have many tasks to perform.
* The idea is that when you reassign a role, it affects all the tasks that role
* has been assigned to.
*
* For the upgrade, we simply create one role per transtiion, and change
* all the other tables correspondingly. This will execute exactly equivalent
* to the way it would have without the roles refactoring.
*
* We've also added other minor things, such as task instructions and gotten rid
* of wf_attribute_info.
*/
/*
* NOTE:
*
* After running this script, you must reload the following two PL/SQL packages:
*
* package/acs-workflow/sql/workflow-package.sql
* package/acs-workflow/sql/workflow-case-package.sql
*/
/*
* Table wf_roles:
* Added.
*/
create table wf_roles (
role_key varchar2(100),
workflow_key varchar2(100)
constraint wf_roles_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
role_name varchar2(100)
constraint wf_role_role_name_nn
not null,
-- so we can display roles in some logical order --
sort_order integer
constraint wf_roles_order_ck
check (sort_order > 0),
-- table constraints --
constraint wf_role_pk
primary key (workflow_key, role_key),
constraint wf_roles_wf_key_role_name_un
unique (workflow_key, role_name)
);
comment on table wf_roles is '
A process has certain roles associated with it, such as "submitter",
"reviewer", "editor", "claimant", etc. For each transition, then, you
specify what role is to perform that task. Thus, two or more tasks can be
performed by one and the same role, so that when the role is reassigned,
it reflects assignments of both tasks. Users and parties are then assigned
to roles instead of directly to tasks.
';
/*
* Now populate the roles table:
* We just create a role per transition, then hook them up
*/
insert into wf_roles
(workflow_key,
role_key,
role_name,
sort_order)
select workflow_key, transition_key, transition_name, sort_order
from wf_transitions;
/*
* Table wf_transitions:
* Added column role_key.
* Added foreign key constraint wf_transition_role_fk.
*/
alter table wf_transitions add (
role_key varchar2(100)
);
alter table wf_transitions add (
constraint wf_transition_role_fk
foreign key (workflow_key,role_key) references wf_roles(workflow_key,role_key)
/* We don't do on delete cascade here, because that would mean that
* when a role is deleted, the transitions associated with that role would be deleted, too */
);
/* Now populate the new column corresponding to the roles we just created:
* Since there's a one-to-one role per transition, and the have the same keys,
* we just set role_key = transition_key
*/
update wf_transitions
set role_key = transition_key;
/*
* Table wf_transition_role_assign_map:
* Added.
* This replaces wf_transtiion_assign_map, since transitions now assign
* roles instead of other transitions.
*/
create table wf_transition_role_assign_map (
workflow_key varchar2(100)
constraint wf_role_asgn_map_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
transition_key varchar2(100),
assign_role_key varchar2(100),
-- table constraints --
constraint wf_role_asgn_map_pk
primary key (workflow_key, transition_key, assign_role_key),
constraint wf_role_asgn_map_trans_fk
foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key)
on delete cascade,
constraint wf_tr_role_asgn_map_asgn_fk
foreign key (workflow_key, assign_role_key) references wf_roles(workflow_key, role_key)
on delete cascade
);
create index wf_role_asgn_map_wf_trans_idx on wf_transition_role_assign_map(workflow_key, transition_key);
create index wf_role_asgn_map_wf_as_tr_idx on wf_transition_role_assign_map(workflow_key, assign_role_key);
comment on table wf_transition_role_assign_map is '
When part of the output of one task is to assign users to a role,
specify that this is the case by inserting a row here.
';
comment on column wf_transition_role_assign_map.transition_key is '
transition_key is the assigning transition.
';
comment on column wf_transition_role_assign_map.assign_role_key is '
assign_role_key is the role being assigned a user to.
';
/* Populate new wf_transition_role_assign_map with the rows from
* wf_transition_assignment_map. Since role_key map one-to-one with transition_keys
* in this upgrade, that's pretty straight-forward.
*/
insert into wf_transition_role_assign_map
(workflow_key,
transition_key,
assign_role_key)
select workflow_key,
transition_key,
assign_transition_key
from wf_transition_assignment_map;
/*
* Table wf_transition_assignment_map:
* Dropped.
* This table is no longer releavnt, since transitions don't assign other
* transitions, they assign roles.
*/
drop table wf_transition_assignment_map;
/*
* Table wf_attribute_info:
* Dropped.
* This table was a hang-over from earlier versions and is no longer necessary.
*/
drop table wf_attribute_info;
/*
* Table wf_context_role_info:
* Added.
*/
create table wf_context_role_info (
context_key varchar2(100)
constraint wf_context_role_context_fk
references wf_contexts(context_key)
on delete cascade,
workflow_key varchar2(100)
constraint wf_context_role_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
role_key varchar2(100),
/*
* Callback to programatically assign a role.
* Must call wordflow_case.*_role_assignment to make the assignments.
* Will be called when a transition for that role becomes enabled
* signature: (role_key in varchar2, custom_arg in varchar2)
*/
assignment_callback varchar2(100),
assignment_custom_arg varchar2(4000),
-- table constraints --
constraint wf_context_role_role_fk
foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key)
on delete cascade,
constraint wf_context_role_info_pk
primary key (context_key, workflow_key, role_key)
);
comment on table wf_context_role_info is '
This table holds context-dependent info for roles, currently only the assignment callback
';
/* Populate by a straight copy from wf_context_transition_info */
insert into wf_context_role_info
(context_key,
workflow_key,
role_key,
assignment_callback,
assignment_custom_arg)
select context_key,
workflow_key,
transition_key,
assignment_callback,
assignment_custom_arg
from wf_context_transition_info
where assignment_callback is not null
or assignment_custom_arg is not null;
/*
* Table wf_context_transition_info:
* Added column 'instructions'.
*/
alter table wf_context_transition_info add (
instructions varchar2(4000)
);
/* Removed columns assignment_callback/custom_arg. */
alter table wf_context_transition_info
drop column assignment_callback;
alter table wf_context_transition_info
drop column assignment_custom_arg;
/* Added on delete cascade to columns workflow_key and .context_key */
alter table wf_context_transition_info
drop constraint wf_context_trans_context_fk;
alter table wf_context_transition_info
add constraint wf_context_trans_context_fk
foreign key (context_key) references wf_contexts (context_key);
alter table wf_context_transition_info
drop constraint wf_context_trans_workflow_fk;
alter table wf_context_transition_info
add constraint wf_context_trans_workflow_fk
foreign key (workflow_key) references wf_workflows (workflow_key);
/*
* Table wf_context_workflow_info:
* Added.
*/
create table wf_context_workflow_info (
context_key varchar2(100)
constraint wf_context_wf_context_fk
references wf_contexts
on delete cascade,
workflow_key varchar2(100)
constraint wf_context_wf_workflow_fk
references wf_workflows
on delete cascade,
/* The principal is the user/party that sends out email assignment notifications
* And receives email when a task becomes unassigned (for more than x minutes?)
*/
principal_party integer
constraint wf_context_wf_principal_fk
references parties
on delete set null,
-- table constraints --
constraint wf_context_workflow_pk
primary key (context_key, workflow_key)
);
/* Insert someone for all existing processes. Hopefully this will be the administrator user. */
insert into wf_context_workflow_info
(context_key,
workflow_key,
principal_party)
select 'default', workflow_key, (select min(party_id) from parties)
from wf_workflows;
/*
* Table wf_context_task_panels:
* Added columns overrides_action_p and only_display_when_started_p
* Renamed column sort_key to sort_order for consistency
*/
alter table wf_context_task_panels add (
/* Display this panel in place of the action panel */
overrides_action_p char(1) default 'f'
constraint wf_context_panels_ovrd_p_ck
check (overrides_action_p in ('t','f')),
/* Display this panel only when the task has been started (and not finished) */
only_display_when_started_p char(1) default 'f'
constraint wf_context_panels_display_p_ck
check (only_display_when_started_p in ('t','f')),
sort_order integer
);
/* Copy over the existing sort_key to the new sort_order */
update wf_context_task_panels
set sort_order = sort_key;
/* Change the primary key */
alter table wf_context_task_panels drop constraint wf_context_panels_pk;
alter table wf_context_task_panels add
constraint wf_context_panels_pk
primary key (context_key, workflow_key, transition_key, sort_order);
/* Drop old sort_key column */
alter table wf_context_task_panels drop column sort_key;
alter table wf_context_task_panels add constraint wf_context_sort_order_nn
check (sort_order is not null);
/*
* Table wf_context_assignments
* Replaced transition_key with role_key
*/
alter table wf_context_assignments add (
role_key varchar2(100),
constraint wf_context_assign_role_fk
foreign key (workflow_key, role_key) references wf_roles (workflow_key, role_key)
on delete cascade
);
alter table wf_context_assignments drop constraint wf_context_assign_trans_fk;
update wf_context_assignments
set role_key = transition_key;
alter table wf_context_assignments drop constraint wf_context_assign_pk;
alter table wf_context_assignments add constraint wf_context_assign_pk
primary key (context_key, workflow_key, role_key, party_id);
alter table wf_context_assignments drop column transition_key;
/*
* Table wf_case_assignments:
* Changed transition_key to role_key
*/
alter table wf_case_assignments add (
role_key varchar2(100),
constraint wf_case_assign_role_fk
foreign key (workflow_key, role_key) references wf_roles (workflow_key, role_key)
on delete cascade
);
update wf_case_assignments
set role_key = transition_key;
alter table wf_case_assignments drop constraint wf_case_assign_pk;
alter table wf_case_assignments add
constraint wf_case_assign_pk
primary key (case_id, role_key, party_id);
alter table wf_case_assignments drop constraint wf_case_assign_trans_fk;
alter table wf_case_assignments drop column transition_key;
/*
* View wf_transition_contexts:
* Added column role_key.
*/
create or replace view wf_transition_contexts as
select t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.role_key,
c.context_key,
c.context_name
from wf_transitions t, wf_contexts c;
/*
* View wf_transition_info:
* Added columns role_key and instructions.
* Removed columns assignment_callback/custom_arg.
*/
create or replace view wf_transition_info as
select t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.context_key,
t.role_key,
ct.estimated_minutes,
ct.instructions,
ct.enable_callback,
ct.enable_custom_arg,
ct.fire_callback,
ct.fire_custom_arg,
ct.time_callback,
ct.time_custom_arg,
ct.deadline_callback,
ct.deadline_custom_arg,
ct.deadline_attribute_name,
ct.hold_timeout_callback,
ct.hold_timeout_custom_arg,
ct.notification_callback,
ct.notification_custom_arg,
ct.unassigned_callback,
ct.unassigned_custom_arg
from wf_transition_contexts t, wf_context_transition_info ct
where ct.workflow_key (+) = t.workflow_key
and ct.transition_key (+) = t.transition_key
and ct.context_key (+) = t.context_key;
/*
* View wf_role_info:
* Added.
*/
create or replace view wf_role_info as
select r.role_key,
r.role_name,
r.workflow_key,
c.context_key,
cr.assignment_callback,
cr.assignment_custom_arg
from wf_roles r, wf_contexts c, wf_context_role_info cr
where cr.workflow_key (+) = r.workflow_key
and cr.role_key (+) = r.role_key
and cr.context_key = c.context_key;
/*
* View wf_enabled_transitions:
* Added columns role_key and instructions.
* Removed columns assignment_callback/custom_arg.
*/
create or replace view wf_enabled_transitions as
select c.case_id,
t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.context_key,
t.role_key,
t.enable_callback,
t.enable_custom_arg,
t.fire_callback,
t.fire_custom_arg,
t.time_callback,
t.time_custom_arg,
t.deadline_callback,
t.deadline_custom_arg,
t.deadline_attribute_name,
t.hold_timeout_callback,
t.hold_timeout_custom_arg,
t.notification_callback,
t.notification_custom_arg,
t.estimated_minutes,
t.instructions,
t.unassigned_callback,
t.unassigned_custom_arg
from wf_transition_info t,
wf_cases c
where t.workflow_key = c.workflow_key
and t.context_key = c.context_key
and c.state = 'active'
and not exists
(select tp.place_key
from wf_transition_places tp
where tp.transition_key = t.transition_key
and tp.workflow_key = t.workflow_key
and tp.direction = 'in'
and not exists
(select tk.token_id
from wf_tokens tk
where tk.place_key = tp.place_key
and tk.case_id = c.case_id
and tk.state = 'free'
)
);
/*
* View wf_user_tasks:
* Added column instructions
* Added "and tr.workflow_key = ta.workflow_key" to where clause
* (looks like a bug)
*/
create or replace view wf_user_tasks as
select distinct ta.task_id,
ta.case_id,
ta.workflow_key,
ta.transition_key,
tr.transition_name,
tr.instructions,
ta.enabled_date,
ta.started_date,
u.user_id,
ta.state,
ta.holding_user,
ta.hold_timeout,
ta.deadline,
ta.estimated_minutes
from wf_tasks ta,
wf_task_assignments tasgn,
wf_cases c,
wf_transition_info tr,
party_approved_member_map m,
users u
where ta.state in ( 'enabled','started')
and c.case_id = ta.case_id
and c.state = 'active'
and tr.transition_key = ta.transition_key
and tr.workflow_key = ta.workflow_key
and tr.trigger_type = 'user'
and tr.context_key = c.context_key
and tasgn.task_id = ta.task_id
and m.party_id = tasgn.party_id
and u.user_id = m.member_id;
/*
* NOTE:
*
* You must reload the following two PL/SQL packages now:
*
* package/acs-workflow/sql/workflow-package.sql
* package/acs-workflow/sql/workflow-case-package.sql
*/
acs-workflow-master/sql/oracle/wf-callback-package-body.sql 0000664 0000000 0000000 00000001661 14575002472 0024256 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/wf-callback-package-body.sql
--
-- Creates the PL/SQL package that provides a small library of reusable
-- workflow callback functions/procedures.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
create or replace package body wf_callback
as
function guard_attribute_true(
case_id in number,
workflow_key in varchar2,
transition_key in varchar2,
place_key in varchar2,
direction in varchar2,
custom_arg in varchar2
) return char
is
begin
return workflow_case.get_attribute_value(
case_id => case_id,
attribute_name => custom_arg
);
end guard_attribute_true;
function time_sysdate_plus_x(
case_id in number,
transition_key in varchar2,
custom_arg in varchar2
) return date
is
begin
return sysdate + to_number(custom_arg);
end time_sysdate_plus_x;
end wf_callback;
/
show errors;
acs-workflow-master/sql/oracle/wf-callback-package-head.sql 0000664 0000000 0000000 00000001262 14575002472 0024217 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/wf-callback-package-head.sql
--
-- Creates the PL/SQL package that provides a small library of reusable
-- workflow callback functions/procedures.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
create or replace package wf_callback
as
function guard_attribute_true(
case_id in number,
workflow_key in varchar2,
transition_key in varchar2,
place_key in varchar2,
direction in varchar2,
custom_arg in varchar2
) return char;
function time_sysdate_plus_x(
case_id in number,
transition_key in varchar2,
custom_arg in varchar2
) return date;
end wf_callback;
/
show errors;
acs-workflow-master/sql/oracle/wf-callback-package.sql 0000664 0000000 0000000 00000000474 14575002472 0023324 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/wf-callback-package.sql
--
-- Creates the PL/SQL package that provides a small library of reusable
-- workflow callback functions/procedures.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
@@wf-callback-package-head
@@wf-callback-package-body
acs-workflow-master/sql/oracle/wf-core-create.sql 0000664 0000000 0000000 00000103265 14575002472 0022372 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/wf-core-create.sql
--
-- Creates the data model and views for the workflow package.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
----------------------------------
-- KNOWLEDGE LEVEL OBJECTS
----------------------------------
/* Create the workflow superclass */
begin
acs_object_type.create_type(
object_type => 'workflow',
pretty_name => 'Workflow',
pretty_plural => 'Workflow',
table_name => 'wf_cases',
id_column => 'case_id'
);
end;
/
show errors
create table wf_workflows (
workflow_key varchar2(100)
constraint wf_workflows_pk
primary key
constraint wf_wf_acs_object_types_fk
references acs_object_types(object_type)
on delete cascade,
description varchar2(4000)
);
comment on table wf_workflows is '
Parent table for the workflow definition.
';
create table wf_places (
place_key varchar2(100),
workflow_key varchar2(100)
constraint wf_place_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
place_name varchar2(100)
constraint wf_place_name_nn
not null,
-- so we can display places in some logical order --
sort_order integer
constraint wf_place_order_ck
check (sort_order > 0),
-- table constraints --
constraint wf_place_pk
primary key (workflow_key, place_key),
constraint wf_places_wf_key_place_name_un
unique (workflow_key, place_name)
);
comment on table wf_places is '
The circles of the petri net. These hold the tokens representing the overall
state of the workflow.
';
create table wf_roles (
role_key varchar2(100),
workflow_key varchar2(100)
constraint wf_roles_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
role_name varchar2(100)
constraint wf_role_role_name_nn
not null,
-- so we can display roles in some logical order --
sort_order integer
constraint wf_roles_order_ck
check (sort_order > 0),
-- table constraints --
constraint wf_role_pk
primary key (workflow_key, role_key),
constraint wf_roles_wf_key_role_name_un
unique (workflow_key, role_name)
);
comment on table wf_roles is '
A process has certain roles associated with it, such as "submitter",
"reviewer", "editor", "claimant", etc. For each transition, then, you
specify what role is to perform that task. Thus, two or more tasks can be
performed by one and the same role, so that when the role is reassigned,
it reflects assignments of both tasks. Users and parties are then assigned
to roles instead of directly to tasks.
';
create table wf_transitions (
transition_key varchar2(100),
transition_name varchar2(100)
constraint wf_transition_name_nn
not null,
workflow_key varchar2(100)
constraint wf_transition_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
-- what role does this transition belong to
-- (only for user-triggered transitions)
role_key varchar2(100),
-- so we can display transitions in some logical order --
sort_order integer
constraint wf_transition_order_ck
check (sort_order > 0),
trigger_type varchar2(40)
constraint wf_transition_trigger_type_ck
check (trigger_type in
('automatic','user','message','time')),
-- table constraints --
constraint wf_transition_pk
primary key (workflow_key, transition_key),
constraint wf_trans_wf_key_trans_name_un
unique (workflow_key, transition_name),
constraint wf_transition_role_fk
foreign key (workflow_key,role_key) references wf_roles(workflow_key,role_key)
/* We don't do on delete cascade here, because that would mean that
* when a role is deleted, the transitions associated with that role would be deleted, too */
);
comment on table wf_transitions is '
The squares in the petri net. The things that somebody (or something) actually does.
';
create table wf_arcs (
workflow_key varchar2(100)
constraint wf_ts_arc_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
transition_key varchar2(100),
place_key varchar2(100),
-- direction is relative to the transition
direction varchar2(3)
constraint wf_arc_direction_ck
check (direction in ('in','out')),
/* Must be satisfied for the arc to be traveled by a token
* This is the name of a PL/SQL function to execute, which must return t or f
* Signature: (case_id in number, workflow_key in varchar2, transition_key in varchar2,
* place_key in varchar2, direction in varchar2, custom_arg in varchar2)
* return char(1)
*/
guard_callback varchar2(100),
guard_custom_arg varchar2(4000),
guard_description varchar2(500),
-- table constraints --
constraint wf_arc_pk
primary key (workflow_key, transition_key, place_key, direction),
constraint wf_arc_guard_on_in_arc_ck
check (guard_callback is null or direction = 'out'),
constraint wf_arc_transition_fk
foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key)
on delete cascade,
constraint wf_arc_place_fk
foreign key (workflow_key, place_key) references wf_places(workflow_key, place_key)
on delete cascade
);
create index wf_arcs_wf_key_trans_key_idx on wf_arcs(workflow_key, transition_key);
create index wf_arcs_wf_key_place_key_idx on wf_arcs(workflow_key, place_key);
comment on table wf_arcs is '
The arcs of the workflow petri net.
Arcs always go between a transition and a place.
The direction is relative to the transition here, i.e.
in means it goes into the transition, out means it goes
away from the transition.
';
create table wf_transition_attribute_map (
workflow_key varchar2(100)
constraint wf_trans_attr_map_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
transition_key varchar2(100),
-- so the user can decide in what order the attributes should be presented
sort_order integer not null,
attribute_id integer
constraint wf_trans_attr_map_attribute_fk
references acs_attributes,
-- table constraints --
constraint wf_trans_attr_map_pk
primary key (workflow_key, transition_key, attribute_id),
constraint wf_trans_attr_map_trans_fk
foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key)
on delete cascade
);
comment on table wf_transition_attribute_map is '
The workflow attributes that should be set when
the given transition is fired.
';
create table wf_transition_role_assign_map (
workflow_key varchar2(100)
constraint wf_role_asgn_map_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
transition_key varchar2(100),
assign_role_key varchar2(100),
-- table constraints --
constraint wf_role_asgn_map_pk
primary key (workflow_key, transition_key, assign_role_key),
constraint wf_role_asgn_map_trans_fk
foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key)
on delete cascade,
constraint wf_tr_role_asgn_map_asgn_fk
foreign key (workflow_key, assign_role_key) references wf_roles(workflow_key, role_key)
on delete cascade
);
create index wf_role_asgn_map_wf_trans_idx on wf_transition_role_assign_map(workflow_key, transition_key);
create index wf_role_asgn_map_wf_as_tr_idx on wf_transition_role_assign_map(workflow_key, assign_role_key);
comment on table wf_transition_role_assign_map is '
When part of the output of one task is to assign users to a role,
specify that this is the case by inserting a row here.
';
comment on column wf_transition_role_assign_map.transition_key is '
transition_key is the assigning transition.
';
comment on column wf_transition_role_assign_map.assign_role_key is '
assign_role_key is the role being assigned a user to.
';
/*
* Contexts
*/
create table wf_contexts (
context_key varchar2(100)
constraint wf_context_pk
primary key,
context_name varchar2(100)
constraint wf_contexts_context_name_nn
not null
constraint wf_contexts_context_name_un
unique
);
comment on table wf_contexts is '
The context of a workflow holds everything that''s not directly
part of the Petri Net structure, the stuff that''s likely to
be changed as the workflow is applied in a real business, and that
you will want to customize across different departments of the
same business. It includes assignments of transitions to parties,
the call-backs, etc.
';
/* Insert a default context that all new cases will use if nothing else is defined */
insert into wf_contexts (context_key, context_name) values ('default', 'Default Context');
commit;
create table wf_context_workflow_info (
context_key varchar2(100)
constraint wf_context_wf_context_fk
references wf_contexts
on delete cascade,
workflow_key varchar2(100)
constraint wf_context_wf_workflow_fk
references wf_workflows
on delete cascade,
/* The principal is the user/party that sends out email assignment notifications
* And receives email when a task becomes unassigned (for more than x minutes?)
*/
principal_party integer
constraint wf_context_wf_principal_fk
references parties
on delete set null,
-- table constraints --
constraint wf_context_workflow_pk
primary key (context_key, workflow_key)
);
comment on table wf_context_workflow_info is '
Holds context-dependent information about the workflow, specifically the
principal user.
';
create table wf_context_transition_info (
context_key varchar2(100)
constraint wf_context_trans_context_fk
references wf_contexts
on delete cascade,
workflow_key varchar2(100)
constraint wf_context_trans_workflow_fk
references wf_workflows
on delete cascade,
transition_key varchar2(100),
/* information for the transition in the context */
/* The number of minutes this task is estimated to take */
estimated_minutes integer,
/* Instructions for how to complete the task. Will be displayed on the task page. */
instructions varchar2(4000),
/*
* Will be called when the transition is enabled/fired.
* signature: (case_id in number, transition_key in varchar2, custom_arg in varchar2)
*/
enable_callback varchar2(100),
enable_custom_arg varchar2(4000),
fire_callback varchar2(100),
fire_custom_arg varchar2(4000),
/*
* Must return the date that the timed transition should fire
* Will be called when the transition is enabled
* signature: (case_id in number, transition_key in varchar2, custom_arg in varchar2) return date
*/
time_callback varchar2(100),
time_custom_arg varchar2(4000),
/*
* Returns the deadline for this task.
* Will be called when the transition becomes enabled
* Signature: (case_id in number, transition_key in varchar2, custom_arg in varchar2) return date
*/
deadline_callback varchar2(100),
deadline_custom_arg varchar2(4000),
/* The name of an attribute that holds the deadline */
deadline_attribute_name varchar2(100),
/*
* Must return the date that the user's hold on the task times out.
* called when the user starts the task.
* signature: (case_id in number, transition_key in varchar2, custom_arg in varchar2) return date
*/
hold_timeout_callback varchar2(100),
hold_timeout_custom_arg varchar2(4000),
/*
* Notification callback
* Will be called when a notification is sent i.e., when a transition is enabled,
* or assignment changes.
* signature: (task_id in number,
* custom_arg in varchar2,
* party_to in integer,
* party_from in out integer,
* subject in out varchar2,
* body in out varchar2)
*/
notification_callback varchar2(100),
notification_custom_arg varchar2(4000),
/*
* Callback to handle unassigned tasks.
* Will be called when an enabled task becomes unassigned.
* Signature: (task_id in number, custom_arg in varchar2)
*/
unassigned_callback varchar2(100),
unassigned_custom_arg varchar2(4000),
-- table constraints --
constraint wf_context_trans_trans_fk
foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key)
on delete cascade,
constraint wf_context_transition_pk
primary key (context_key, workflow_key, transition_key)
);
create index wf_ctx_trans_wf_trans_idx on wf_context_transition_info(workflow_key, transition_key);
comment on table wf_context_transition_info is '
This table holds information that pertains to a transition in a specific context.
It will specifically hold
';
create table wf_context_role_info (
context_key varchar2(100)
constraint wf_context_role_context_fk
references wf_contexts(context_key)
on delete cascade,
workflow_key varchar2(100)
constraint wf_context_role_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
role_key varchar2(100),
/*
* Callback to programatically assign a role.
* Must call wordflow_case.*_role_assignment to make the assignments.
* Will be called when a transition for that role becomes enabled
* signature: (role_key in varchar2, custom_arg in varchar2)
*/
assignment_callback varchar2(100),
assignment_custom_arg varchar2(4000),
-- table constraints --
constraint wf_context_role_role_fk
foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key)
on delete cascade,
constraint wf_context_role_info_pk
primary key (context_key, workflow_key, role_key)
);
comment on table wf_context_role_info is '
This table holds context-dependent info for roles, currently only the assignment callback
';
create table wf_context_task_panels (
context_key varchar2(100) not null
constraint wf_context_panels_context_fk
references wf_contexts(context_key)
on delete cascade,
workflow_key varchar2(100) not null
constraint wf_context_panels_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
transition_key varchar2(100) not null,
sort_order integer not null,
header varchar2(200) not null,
template_url varchar2(500) not null,
/* Display this panel in place of the action panel */
overrides_action_p char(1) default 'f'
constraint wf_context_panels_ovrd_p_ck
check (overrides_action_p in ('t','f')),
/* Display this panel only when the task has been started (and not finished) */
only_display_when_started_p char(1) default 'f'
constraint wf_context_panels_display_p_ck
check (only_display_when_started_p in ('t','f')),
-- table constraints --
constraint wf_context_panels_trans_fk
foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key)
on delete cascade,
constraint wf_context_panels_pk
primary key (context_key, workflow_key, transition_key, sort_order)
);
create index wf_ctx_panl_workflow_trans_idx on wf_context_task_panels(workflow_key, transition_key);
comment on table wf_context_task_panels is '
Holds information about the panels to be displayed on the task page.
';
create table wf_context_assignments (
context_key varchar2(100)
constraint wf_context_assign_context_fk
references wf_contexts(context_key)
on delete cascade,
workflow_key varchar2(100)
constraint wf_context_assign_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
role_key varchar2(100),
party_id integer
constraint wf_context_assign_party_fk
references parties(party_id)
on delete cascade,
-- table constraints --
constraint wf_context_assign_pk
primary key (context_key, workflow_key, role_key, party_id),
constraint wf_context_assign_role_fk
foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key)
on delete cascade
);
create index wf_ctx_assg_workflow_trans_idx on wf_context_assignments(workflow_key, role_key);
comment on table wf_context_assignments is '
Static (default) per-context assignments of roles to parties.
';
------------------------------------
-- OPERATIONAL LEVEL OBJECTS
------------------------------------
create table wf_cases (
case_id integer
constraint wf_cases_pk
primary key
constraint wf_cases_acs_object_fk
references acs_objects(object_id)
on delete cascade,
workflow_key varchar2(100)
constraint wf_cases_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
context_key varchar2(100)
constraint wf_cases_context_fk
references wf_contexts(context_key)
on delete cascade,
object_id constraint wf_cases_object_fk
references acs_objects(object_id)
on delete cascade,
-- a toplevel state of the case
state varchar2(40)
default 'created'
constraint wf_cases_state_ck
check (state in ('created',
'active',
'suspended',
'canceled',
'finished'))
);
create index wf_cases_workflow_key_idx on wf_cases(workflow_key);
create index wf_cases_context_key_idx on wf_cases(context_key);
create index wf_cases_object_id_idx on wf_cases(object_id);
comment on table wf_cases is '
The instance of a process, e.g. the case of publishing one article,
the case of handling one insurance claim, the case of handling
one ecommerce order, of fixing one ticket-tracker ticket.
';
comment on column wf_cases.object_id is '
A case is generally about some other object, e.g., an insurance claim, an article,
a ticket, an order, etc. This is the place to store the reference to that object.
It is not uncommong to have more than one case for the same object, e.g., we might
have one process for evaluating and honoring an insurance claim, and another for archiving
legal information about a claim.
';
create table wf_case_assignments (
case_id integer
constraint wf_case_assign_fk
references wf_cases(case_id)
on delete cascade,
workflow_key varchar2(100),
role_key varchar2(100),
party_id integer
constraint wf_case_assign_party_fk
references parties(party_id)
on delete cascade,
-- table constraints --
constraint wf_case_assign_pk
primary key (case_id, role_key, party_id),
constraint wf_case_assign_role_fk
foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key)
on delete cascade
);
create index wf_case_assgn_party_idx on wf_case_assignments(party_id);
comment on table wf_case_assignments is '
Manual per-case assignments of roles to parties.
';
create table wf_case_deadlines (
case_id integer
constraint wf_case_deadline_fk
references wf_cases(case_id)
on delete cascade,
workflow_key varchar2(100),
transition_key varchar2(100),
deadline date
constraint wf_case_deadline_nn
not null,
-- table constraints --
constraint wf_case_deadline_pk
primary key (case_id, transition_key),
constraint wf_case_deadline_trans_fk
foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key)
on delete cascade
);
comment on table wf_case_deadlines is '
Manual deadlines for the individual transitions (tasks) on a per-case basis.
';
create sequence wf_task_id_seq start with 1000 increment by 1;
create table wf_tasks (
task_id integer
constraint wf_task_pk
primary key,
case_id integer
constraint wf_task_case_fk
references wf_cases
on delete cascade,
workflow_key varchar2(100)
constraint wf_task_workflow_fk
references wf_workflows(workflow_key),
transition_key varchar2(100),
/* Information about the task */
state varchar2(40)
default 'enabled'
constraint wf_task_state_ck
check (state in ('enabled','started','canceled',
'finished','overridden')),
enabled_date date default sysdate,
started_date date,
canceled_date date,
finished_date date,
overridden_date date,
/* -- TIME transition info */
trigger_time date,
/* -- USER transition info */
deadline date,
estimated_minutes integer,
holding_user integer
constraint wf_task_holding_user_fk
references users(user_id)
on delete cascade,
hold_timeout date,
-- table constraints --
constraint wf_task_transition_fk
foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key)
);
create index wf_tasks_case_id_idx on wf_tasks(case_id);
create index wf_tasks_holding_user_idx on wf_tasks(holding_user);
comment on table wf_tasks is '
The tasks that need to be done, who can do it, and what state it''s in.
A task is the instance of a transition.
';
create table wf_task_assignments (
task_id integer
constraint wf_task_assign_task_fk
references wf_tasks(task_id)
on delete cascade,
party_id integer
constraint wf_task_party_fk
references parties(party_id)
on delete cascade,
-- table constraints --
constraint wf_task_assignments_pk
primary key (task_id, party_id)
);
create index wf_task_asgn_party_id_idx on wf_task_assignments(party_id);
create sequence wf_token_id_seq start with 1000 increment by 1;
create table wf_tokens (
token_id integer
constraint wf_token_pk
primary key,
case_id integer
constraint wf_token_workflow_instance_fk
references wf_cases(case_id)
on delete cascade,
workflow_key varchar2(100)
constraint wf_token_workflow_fk
references wf_workflows(workflow_key),
-- a token must always be in some place
place_key varchar2(100),
state varchar2(40) default 'free'
constraint wf_tokens_state_ck
check (state in ('free', 'locked', 'canceled', 'consumed')),
-- when the token is locked, by which task
locked_task_id integer
constraint wf_token_task_fk
references wf_tasks(task_id),
-- info on state changes
produced_date date default sysdate,
locked_date date,
canceled_date date,
consumed_date date,
produced_journal_id integer
constraint wf_token_produced_journal_fk
references journal_entries(journal_id),
locked_journal_id integer
constraint wf_token_locked_journal_fk
references journal_entries(journal_id),
canceled_journal_id integer
constraint wf_token_canceled_journal_fk
references journal_entries(journal_id),
consumed_journal_id integer
constraint wf_token_consumed_journal_fk
references journal_entries(journal_id),
-- table constraints --
constraint wf_token_place_fk
foreign key (workflow_key, place_key) references wf_places(workflow_key, place_key)
);
create index wf_tokens_case_id_idx on wf_tokens(case_id);
comment on table wf_tokens is '
Where the tokens currently are, and what task is laying hands on it, if any.
A token is sort of the instance of a place, except there''ll be one row here per
token, and there can be more than one token per place.
';
/* Should evetually be done by acs_objects automatically */
create table wf_attribute_value_audit (
case_id integer
constraint wf_attr_val_audit_case_fk
references wf_cases(case_id)
on delete cascade,
attribute_id integer
constraint wf_attr_val_audit_attr_fk
references acs_attributes(attribute_id)
on delete cascade,
journal_id integer
constraint wf_attr_val_audit_journal_fk
references journal_entries(journal_id),
attr_value varchar2(4000),
-- table constraints --
constraint wf_attr_val_audit_pk
primary key (case_id, attribute_id, journal_id)
);
create index wf_attr_val_aud_attr_id_idx on wf_attribute_value_audit(attribute_id);
comment on table wf_attribute_value_audit is '
This table holds all the attribute values that has been set,
so we can track changes over the lifetime of a case.
';
/*
* This is the cartesian product of transitions and contexts.
* We need this in order to compute the following wf_transition_info view,
* because Oracle won't let us outer join against more than one table.
*/
create or replace view wf_transition_contexts as
select t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.role_key,
c.context_key,
c.context_name
from wf_transitions t, wf_contexts c;
/*
* Returns all the information stored about a certain transition
* in all contexts. You'll usually want to use this with a
* "where context = " clause.
*/
create or replace view wf_transition_info as
select t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.context_key,
t.role_key,
ct.estimated_minutes,
ct.instructions,
ct.enable_callback,
ct.enable_custom_arg,
ct.fire_callback,
ct.fire_custom_arg,
ct.time_callback,
ct.time_custom_arg,
ct.deadline_callback,
ct.deadline_custom_arg,
ct.deadline_attribute_name,
ct.hold_timeout_callback,
ct.hold_timeout_custom_arg,
ct.notification_callback,
ct.notification_custom_arg,
ct.unassigned_callback,
ct.unassigned_custom_arg
from wf_transition_contexts t, wf_context_transition_info ct
where ct.workflow_key (+) = t.workflow_key
and ct.transition_key (+) = t.transition_key
and ct.context_key (+) = t.context_key;
/*
* Returns all the information stored about a certain role
* in all contexts. You'll usually want to use this with a
* "where context = " clause.
*/
create or replace view wf_role_info as
select r.role_key,
r.role_name,
r.workflow_key,
c.context_key,
cr.assignment_callback,
cr.assignment_custom_arg
from wf_roles r, wf_contexts c, wf_context_role_info cr
where cr.workflow_key (+) = r.workflow_key
and cr.role_key (+) = r.role_key
and cr.context_key = c.context_key;
/*
* This view makes it easy to get the input/output places of a transition
*/
create or replace view wf_transition_places as
select a.workflow_key,
t.transition_key,
p.place_key,
p.place_name,
p.sort_order,
a.direction,
a.guard_callback,
a.guard_custom_arg,
a.guard_description
from wf_arcs a, wf_places p, wf_transitions t
where a.transition_key = t.transition_key
and a.workflow_key = t.workflow_key
and p.place_key = a.place_key
and p.workflow_key = a.workflow_key;
/*
* This view returns information about all currently enabled transitions.
* It does not include transitions that are started. This information, along
* with additional, dynamic information, such as the user assignment or the
* time a timed transition triggers, is then stored in wf_tasks.
*
* Contrary to wf_tasks, this is authoritative, in that it queries
* the actual state of the workflow net.
*
* The logic behind this view is: All transitions in all cases, for which
* there does not exists a place for which there is not a free token.
*/
create or replace view wf_enabled_transitions as
select c.case_id,
t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.context_key,
t.role_key,
t.enable_callback,
t.enable_custom_arg,
t.fire_callback,
t.fire_custom_arg,
t.time_callback,
t.time_custom_arg,
t.deadline_callback,
t.deadline_custom_arg,
t.deadline_attribute_name,
t.hold_timeout_callback,
t.hold_timeout_custom_arg,
t.notification_callback,
t.notification_custom_arg,
t.estimated_minutes,
t.instructions,
t.unassigned_callback,
t.unassigned_custom_arg
from wf_transition_info t,
wf_cases c
where t.workflow_key = c.workflow_key
and t.context_key = c.context_key
and c.state = 'active'
and not exists
(select tp.place_key
from wf_transition_places tp
where tp.transition_key = t.transition_key
and tp.workflow_key = t.workflow_key
and tp.direction = 'in'
and not exists
(select tk.token_id
from wf_tokens tk
where tk.place_key = tp.place_key
and tk.case_id = c.case_id
and tk.state = 'free'
)
);
/*
* This view joins wf_tasks with the parties data model to figure out who can perform the tasks.
* It should contain one row per ( user x task )
*/
/* Replaced 'unique' with 'distinct', because Stas had problems with Oracle behaving mysteriously */
create or replace view wf_user_tasks as
select distinct ta.task_id,
ta.case_id,
ta.workflow_key,
ta.transition_key,
tr.transition_name,
tr.instructions,
ta.enabled_date,
ta.started_date,
u.user_id,
ta.state,
ta.holding_user,
ta.hold_timeout,
ta.deadline,
ta.estimated_minutes
from wf_tasks ta,
wf_task_assignments tasgn,
wf_cases c,
wf_transition_info tr,
party_approved_member_map m,
users u
where ta.state in ( 'enabled','started')
and c.case_id = ta.case_id
and c.state = 'active'
and tr.transition_key = ta.transition_key
and tr.workflow_key = ta.workflow_key
and tr.trigger_type = 'user'
and tr.context_key = c.context_key
and tasgn.task_id = ta.task_id
and m.party_id = tasgn.party_id
and u.user_id = m.member_id;
acs-workflow-master/sql/oracle/wf-core-drop.sql 0000664 0000000 0000000 00000003316 14575002472 0022067 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/wf-core-drop.sql
--
-- Drops the data model and views for the workflow package.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
/* Drop all cases and all workflows */
begin
for workflow_rec in (select w.workflow_key, t.table_name
from wf_workflows w, acs_object_types t
where t.object_type = w.workflow_key)
loop
workflow.delete_cases(workflow_key => workflow_rec.workflow_key);
execute immediate 'drop table '||workflow_rec.table_name;
workflow.drop_workflow(workflow_key => workflow_rec.workflow_key);
end loop;
end;
/
show errors;
/* Sequences */
drop sequence wf_task_id_seq;
drop sequence wf_token_id_seq;
/* Views */
drop view wf_user_tasks;
drop view wf_enabled_transitions;
drop view wf_transition_places;
drop view wf_role_info;
drop view wf_transition_info;
drop view wf_transition_contexts;
/* Operational level */
drop table wf_attribute_value_audit;
drop table wf_tokens;
drop table wf_task_assignments;
drop table wf_tasks;
drop table wf_case_assignments;
drop table wf_case_deadlines;
drop table wf_cases;
/* Context level */
drop table wf_context_assignments;
drop table wf_context_task_panels;
drop table wf_context_role_info;
drop table wf_context_transition_info;
drop table wf_context_workflow_info;
drop table wf_contexts;
/* Knowledge Level */
drop table wf_transition_role_assign_map;
drop table wf_transition_attribute_map;
drop table wf_arcs;
drop table wf_transitions;
drop table wf_roles;
drop table wf_places;
drop table wf_workflows;
/* acs_object_type */
begin
acs_object_type.drop_type(
object_type => 'workflow',
cascade_p => 't'
);
end;
/
show errors
acs-workflow-master/sql/oracle/workflow-case-package-body.sql 0000664 0000000 0000000 00000200475 14575002472 0024677 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/workflow-case-package-body.sql
--
-- Creates the PL/SQL package that provides the API for interacting
-- with a workflow case.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
create or replace package body workflow_case
is
/*
* FORWARD DECLARATIONS
*/
procedure add_token (
case_id in number,
place_key in varchar2,
journal_id in number
);
procedure lock_token (
case_id in number,
place_key in varchar2,
journal_id in number,
task_id in number
);
procedure release_token (
task_id in number,
journal_id in number
);
procedure consume_token (
case_id in number,
place_key in varchar2,
journal_id in number,
task_id in number default null
);
procedure execute_unassigned_callback (
callback in varchar2,
task_id in number,
custom_arg in varchar2
);
procedure enable_transitions (
case_id in number
);
procedure sweep_automatic_transitions (
case_id in number,
journal_id in number
);
function finished_p(
case_id in number,
journal_id in number
) return char;
procedure fire_transition_internal (
task_id in number,
journal_id in number
);
procedure start_task(
task_id in number,
user_id in number,
journal_id in number
);
procedure cancel_task(
task_id in number,
journal_id in number
);
procedure finish_task (
task_id in number,
journal_id in number
);
procedure notify_assignee(
task_id in wf_tasks.task_id%TYPE,
user_id in users.user_id%TYPE,
callback in wf_context_transition_info.notification_callback%TYPE,
custom_arg in wf_context_transition_info.notification_custom_arg%TYPE
);
/*
* CURSORS
*/
cursor input_places(
workflow_key in wf_workflows.workflow_key%TYPE,
transition_key in wf_transitions.transition_key%TYPE
)
return wf_transition_places%ROWTYPE
is
select *
from wf_transition_places tp
where tp.workflow_key = input_places.workflow_key
and tp.transition_key = input_places.transition_key
and direction = 'in';
cursor output_places (
workflow_key in wf_workflows.workflow_key%TYPE,
transition_key in wf_transitions.transition_key%TYPE
)
return wf_transition_places%ROWTYPE
is
select *
from wf_transition_places tp
where tp.workflow_key = output_places.workflow_key
and tp.transition_key = output_places.transition_key
and direction = 'out';
/*
* PUBLIC API
*/
function new (
case_id in number default null,
workflow_key in varchar2,
context_key in varchar2 default null,
object_id in integer,
creation_date in date default sysdate,
creation_user in integer default null,
creation_ip in varchar2 default null
)
return integer
is
v_case_id number;
v_workflow_case_table varchar2(30);
v_context_key_for_query varchar2(100);
begin
if context_key is null then
v_context_key_for_query := 'default';
else
v_context_key_for_query := context_key;
end if;
/* insert a row into acs_objects */
v_case_id := acs_object.new(
object_id => new.case_id,
object_type => new.workflow_key,
creation_date => new.creation_date,
creation_user => new.creation_user,
creation_ip => new.creation_ip
);
/* insert the case in to the general wf_cases table */
insert into wf_cases
(case_id, workflow_key, context_key, object_id, state)
values
(v_case_id, new.workflow_key, v_context_key_for_query, new.object_id, 'created');
/* insert the case into the workflow-specific cases table */
select table_name into v_workflow_case_table
from acs_object_types
where object_type = new.workflow_key;
execute immediate 'insert into '||v_workflow_case_table||' (case_id) values (:1)'
using v_case_id;
return v_case_id;
end new;
procedure add_manual_assignment (
case_id in number,
role_key in varchar2,
party_id in number
)
is
v_workflow_key varchar2(100);
v_num_rows integer;
begin
select count(*)
into v_num_rows
from wf_case_assignments
where case_id = add_manual_assignment.case_id
and role_key = add_manual_assignment.role_key
and party_id = add_manual_assignment.party_id;
if v_num_rows = 0 then
select workflow_key
into v_workflow_key
from wf_cases
where case_id = add_manual_assignment.case_id;
insert into wf_case_assignments (
case_id,
workflow_key,
role_key,
party_id
) values (
add_manual_assignment.case_id,
v_workflow_key,
add_manual_assignment.role_key,
add_manual_assignment.party_id
);
end if;
end add_manual_assignment;
procedure remove_manual_assignment (
case_id in number,
role_key in varchar2,
party_id in number
)
is
v_workflow_key varchar2(100);
begin
select workflow_key
into v_workflow_key
from wf_cases
where case_id = remove_manual_assignment.case_id;
delete
from wf_case_assignments
where workflow_key = v_workflow_key
and case_id = remove_manual_assignment.case_id
and role_key = remove_manual_assignment.role_key
and party_id = remove_manual_assignment.party_id;
end remove_manual_assignment;
procedure clear_manual_assignments (
case_id in number,
role_key in varchar2
)
is
v_workflow_key varchar2(100);
begin
select workflow_key
into v_workflow_key
from wf_cases
where case_id = clear_manual_assignments.case_id;
delete
from wf_case_assignments
where workflow_key = v_workflow_key
and case_id = clear_manual_assignments.case_id
and role_key = clear_manual_assignments.role_key;
end clear_manual_assignments;
procedure start_case (
case_id in number,
creation_user in integer default null,
creation_ip in varchar2 default null,
msg in varchar2 default null
)
is
v_journal_id number;
begin
/* Add an entry to the journal */
v_journal_id := journal_entry.new(
object_id => start_case.case_id,
action => 'case start',
action_pretty => 'Case started',
creation_user => start_case.creation_user,
creation_ip => start_case.creation_ip,
msg => start_case.msg
);
update wf_cases set state = 'active' where case_id = start_case.case_id;
add_token(
case_id => start_case.case_id,
place_key => 'start',
journal_id => v_journal_id
);
/* Turn the wheels */
sweep_automatic_transitions(
case_id => start_case.case_id,
journal_id => v_journal_id
);
end start_case;
procedure del (
case_id in number
)
is
v_workflow_case_table varchar2(30);
begin
/* delete attribute_value_audit, tokens, tasks */
delete from wf_attribute_value_audit where case_id = workflow_case.del.case_id;
delete from wf_case_assignments where case_id = workflow_case.del.case_id;
delete from wf_case_deadlines where case_id = workflow_case.del.case_id;
delete from wf_tokens where case_id = workflow_case.del.case_id;
delete from wf_task_assignments where task_id in (select task_id from wf_tasks where case_id = workflow_case.del.case_id);
delete from wf_tasks where case_id = workflow_case.del.case_id;
/* delete the journal */
journal_entry.delete_for_object(workflow_case.del.case_id);
/* delete from the workflow-specific cases table */
select table_name into v_workflow_case_table
from acs_object_types ot, wf_cases c
where c.case_id = workflow_case.del.case_id
and object_type = c.workflow_key;
execute immediate 'delete from '||v_workflow_case_table||' where case_id = :case_id'
using in workflow_case.del.case_id;
/* delete from the generic cases table */
delete from wf_cases where case_id = workflow_case.del.case_id;
/* delete from acs-objects */
acs_object.del(workflow_case.del.case_id);
end del;
procedure suspend(
case_id in number,
user_id in number default null,
ip_address in varchar2 default null,
msg in varchar2 default null
)
is
v_state varchar2(40);
v_journal_id number;
begin
select state into v_state
from wf_cases
where case_id = suspend.case_id;
if v_state != 'active' then
raise_application_error(-20000, 'Only active cases can be suspended');
end if;
/* Add an entry to the journal */
v_journal_id := journal_entry.new(
object_id => suspend.case_id,
action => 'case suspend',
action_pretty => 'case suspended',
creation_user => suspend.user_id,
creation_ip => suspend.ip_address,
msg => suspend.msg
);
update wf_cases
set state = 'suspended'
where case_id = suspend.case_id;
end suspend;
procedure resume(
case_id in number,
user_id in number default null,
ip_address in varchar2 default null,
msg in varchar2 default null
)
is
v_state varchar2(40);
v_journal_id number;
begin
select state into v_state
from wf_cases
where case_id = resume.case_id;
if v_state != 'suspended' and v_state != 'canceled' then
raise_application_error(-20000, 'Only suspended or canceled cases can be resumed');
end if;
/* Add an entry to the journal */
v_journal_id := journal_entry.new(
object_id => resume.case_id,
action => 'case resume',
action_pretty => 'case resumed',
creation_user => resume.user_id,
creation_ip => resume.ip_address,
msg => resume.msg
);
update wf_cases
set state = 'active'
where case_id = resume.case_id;
end resume;
procedure cancel(
case_id in number,
user_id in number default null,
ip_address in varchar2 default null,
msg in varchar2 default null
)
is
v_state varchar2(40);
v_journal_id number;
begin
select state into v_state
from wf_cases
where case_id = cancel.case_id;
if v_state != 'active' and v_state != 'suspended' then
raise_application_error(-20000, 'Only active or suspended cases can be canceled');
end if;
/* Add an entry to the journal */
v_journal_id := journal_entry.new(
object_id => cancel.case_id,
action => 'case cancel',
action_pretty => 'Case canceled',
creation_user => cancel.user_id,
creation_ip => cancel.ip_address,
msg => cancel.msg
);
update wf_cases
set state = 'canceled'
where case_id = cancel.case_id;
end cancel;
procedure fire_message_transition (
task_id in number
) is
v_case_id number;
v_transition_name varchar2(100);
v_trigger_type varchar2(40);
v_journal_id number;
begin
select t.case_id, tr.transition_name, tr.trigger_type
into v_case_id, v_transition_name, v_trigger_type
from wf_tasks t, wf_transitions tr
where t.task_id = fire_message_transition.task_id
and tr.workflow_key = t.workflow_key
and tr.transition_key = t.transition_key;
if v_trigger_type != 'message' then
raise_application_error(-20000, 'Transition '''||v_transition_name||''' is not message triggered');
end if;
/* Add an entry to the journal */
v_journal_id := journal_entry.new(
object_id => v_case_id,
action => 'task '||fire_message_transition.task_id||' fire',
action_pretty => v_transition_name || ' fired'
);
fire_transition_internal(
task_id => fire_message_transition.task_id,
journal_id => v_journal_id
);
sweep_automatic_transitions(
case_id => v_case_id,
journal_id => v_journal_id
);
end fire_message_transition;
/*
* A wrapper for user tasks that uses the start/commit/cancel model for firing transitions.
* Returns journal_id.
*/
function begin_task_action (
task_id in number,
action in varchar2,
action_ip in varchar2,
user_id in number,
msg in varchar2 default null
)
return number
is
v_state varchar2(40);
v_journal_id number;
v_case_id number;
v_transition_name varchar2(100);
v_num_rows number;
begin
select state into v_state
from wf_tasks
where task_id = begin_task_action.task_id;
if begin_task_action.action = 'start' then
if v_state != 'enabled' then
raise_application_error(-20000, 'Task is in state '''||v_state||''', '||
'but it must be in state ''enabled'' to be started.');
end if;
select decode(count(*),0,0,1) into v_num_rows
from wf_user_tasks
where task_id = begin_task_action.task_id
and user_id = begin_task_action.user_id;
if v_num_rows = 0 then
raise_application_error(-20000, 'You are not assigned to this task.');
end if;
elsif begin_task_action.action = 'finish' or begin_task_action.action = 'cancel' then
if v_state = 'started' then
/* Is this user the holding user? */
select decode(count(*),0,0,1) into v_num_rows
from wf_tasks
where task_id = begin_task_action.task_id
and holding_user = begin_task_action.user_id;
if v_num_rows = 0 then
raise_application_error(-20000, 'You are not the user currently working on this task.');
end if;
elsif v_state = 'enabled' then
if begin_task_action.action = 'cancel' then
raise_application_error(-20000, 'You can only cancel a task in state ''started'', '||
'but this task is in state '''||v_state||'''');
end if;
/* Is this user assigned to this task? */
select decode(count(*),0,0,1) into v_num_rows
from wf_user_tasks
where task_id = begin_task_action.task_id
and user_id = begin_task_action.user_id;
if v_num_rows = 0 then
raise_application_error(-20000, 'You are not assigned to this task.');
end if;
/* This task is finished without an explicit start.
* Store the user as the holding_user */
update wf_tasks
set holding_user = begin_task_action.user_id
where task_id = begin_task_action.task_id;
else
raise_application_error(-20000, 'Task is in state '''||v_state||''', '||
'but it must be in state ''enabled'' or ''started'' to be finished');
end if;
elsif begin_task_action.action = 'comment' then
-- We currently allow anyone to comment on a task
-- (need this line because PL/SQL doens't like empty if blocks)
v_num_rows := 0;
end if;
select t.case_id, tr.transition_name into v_case_id, v_transition_name
from wf_tasks t,
wf_transitions tr
where t.task_id = begin_task_action.task_id
and tr.workflow_key = t.workflow_key
and tr.transition_key = t.transition_key;
/* Insert a journal entry */
v_journal_id := journal_entry.new(
object_id => v_case_id,
action => 'task '||begin_task_action.task_id||' '||begin_task_action.action,
action_pretty => v_transition_name || ' ' || begin_task_action.action,
creation_user => begin_task_action.user_id,
creation_ip => begin_task_action.action_ip,
msg => begin_task_action.msg
);
return v_journal_id;
end begin_task_action;
procedure end_task_action (
journal_id in number,
action in varchar2,
task_id in number
)
is
v_user_id number;
begin
select creation_user into v_user_id
from acs_objects
where object_id = end_task_action.journal_id;
/* Update the workflow state */
if end_task_action.action = 'start' then
start_task(end_task_action.task_id, v_user_id, end_task_action.journal_id);
elsif end_task_action.action = 'finish' then
finish_task(end_task_action.task_id, end_task_action.journal_id);
elsif end_task_action.action = 'cancel' then
cancel_task(end_task_action.task_id, end_task_action.journal_id);
elsif end_task_action.action != 'comment' then
raise_application_error(-20000, 'Unknown action ''' || end_task_action.action || '''');
end if;
end end_task_action;
function task_action (
task_id in number,
action in varchar2,
action_ip in varchar2,
user_id in number,
msg in varchar2 default null
) return number
is
v_journal_id integer;
begin
v_journal_id := begin_task_action(
task_id => task_action.task_id,
action => task_action.action,
action_ip => task_action.action_ip,
user_id => task_action.user_id,
msg => task_action.msg
);
end_task_action(
journal_id => v_journal_id,
action => task_action.action,
task_id => task_action.task_id
);
return v_journal_id;
end task_action;
procedure set_attribute_value (
journal_id in number,
attribute_name in varchar2,
value in varchar2
)
is
v_workflow_key varchar2(100);
v_case_id number;
v_attribute_id number;
begin
select o.object_type, o.object_id into v_workflow_key, v_case_id
from journal_entries je, acs_objects o
where je.journal_id = set_attribute_value.journal_id
and o.object_id = je.object_id;
select attribute_id into v_attribute_id
from acs_attributes
where object_type = v_workflow_key
and attribute_name = set_attribute_value.attribute_name;
acs_object.set_attribute(
object_id_in => v_case_id,
attribute_name_in => set_attribute_value.attribute_name,
value_in => set_attribute_value.value
);
insert into wf_attribute_value_audit
(case_id, attribute_id, journal_id, attr_value)
values
(v_case_id, v_attribute_id, set_attribute_value.journal_id, set_attribute_value.value);
end set_attribute_value;
function get_attribute_value (
case_id in number,
attribute_name in varchar2
)
return varchar2
is
begin
return acs_object.get_attribute(
object_id_in => get_attribute_value.case_id,
attribute_name_in => get_attribute_value.attribute_name
);
end get_attribute_value;
procedure add_task_assignment (
task_id in number,
party_id in number,
permanent_p in char default 'f'
)
is
v_count integer;
v_workflow_key wf_workflows.workflow_key%TYPE;
v_context_key wf_contexts.context_key%TYPE;
v_case_id wf_cases.case_id%TYPE;
v_role_key wf_roles.role_key%TYPE;
v_transition_key wf_transitions.transition_key%TYPE;
v_notification_callback wf_context_transition_info.notification_callback%TYPE;
v_notification_custom_arg wf_context_transition_info.notification_custom_arg%TYPE;
-- might need to tune this query further
cursor c_new_assigned_users is
select distinct u.user_id
from users u
where u.user_id not in (
select distinct u2.user_id
from wf_task_assignments tasgn2,
party_approved_member_map m2,
users u2
where tasgn2.task_id = add_task_assignment.task_id
and m2.party_id = tasgn2.party_id
and u2.user_id = m2.member_id)
and exists (
select 1
from party_approved_member_map m
where m.member_id = u.user_id
and m.party_id = add_task_assignment.party_id
);
cursor c_callback is
select notification_callback,
notification_custom_arg
from wf_context_transition_info
where context_key = v_context_key
and workflow_key = v_workflow_key
and transition_key = v_transition_key;
callback_rec c_callback%ROWTYPE;
begin
-- get some needed information
select ta.case_id, ta.workflow_key, ta.transition_key, tr.role_key, c.context_key
into v_case_id, v_workflow_key, v_transition_key, v_role_key, v_context_key
from wf_tasks ta, wf_transitions tr, wf_cases c
where ta.task_id = add_task_assignment.task_id
and tr.workflow_key = ta.workflow_key
and tr.transition_key = ta.transition_key
and c.case_id = ta.case_id;
-- make the same assignment as a manual assignment
if permanent_p = 't' then
/* We do this up-front, because
* even though the user already had a task assignment,
* he might not have a case assignment.
*/
add_manual_assignment(
case_id => v_case_id,
role_key => v_role_key,
party_id => add_task_assignment.party_id
);
end if;
-- check that we don't hit the unique constraint
select count(*) into v_count
from wf_task_assignments
where task_id = add_task_assignment.task_id
and party_id = add_task_assignment.party_id;
if v_count > 0 then
return;
end if;
-- get callback information
open c_callback;
fetch c_callback into callback_rec;
if c_callback%FOUND then
v_notification_callback := callback_rec.notification_callback;
v_notification_custom_arg := callback_rec.notification_custom_arg;
else
v_notification_callback := null;
v_notification_custom_arg := null;
end if;
-- notify any new assignees
for v_assigned_user in c_new_assigned_users loop
notify_assignee(
task_id => add_task_assignment.task_id,
user_id => v_assigned_user.user_id,
callback => v_notification_callback,
custom_arg => v_notification_custom_arg
);
end loop;
-- do the insert
insert into wf_task_assignments (
task_id,
party_id
) values (
add_task_assignment.task_id,
add_task_assignment.party_id
);
end add_task_assignment;
procedure remove_task_assignment (
task_id in number,
party_id in number,
permanent_p in char default 'f'
)
is
v_num_assigned number;
v_case_id number;
v_role_key wf_roles.role_key%TYPE;
v_workflow_key varchar2(100);
v_transition_key varchar2(100);
v_context_key varchar2(100);
cursor c_callback is
select unassigned_callback, unassigned_custom_arg
from wf_context_transition_info
where workflow_key = v_workflow_key
and context_key = v_context_key
and transition_key = v_transition_key;
callback_rec c_callback%ROWTYPE;
begin
-- get some information
select ta.case_id, ta.transition_key, tr.role_key, ta.workflow_key, c.context_key
into v_case_id, v_transition_key, v_role_key, v_workflow_key, v_context_key
from wf_tasks ta, wf_transitions tr, wf_cases c
where ta.task_id = remove_task_assignment.task_id
and tr.workflow_key = ta.workflow_key
and tr.transition_key = ta.transition_key
and c.case_id = ta.case_id;
-- make the same assignment as a manual assignment
if permanent_p = 't' then
remove_manual_assignment(
case_id => v_case_id,
role_key => v_role_key,
party_id => remove_task_assignment.party_id
);
end if;
-- now delete the row
delete
from wf_task_assignments
where task_id = remove_task_assignment.task_id
and party_id = remove_task_assignment.party_id;
-- check if the task now became unassigned
select count(*)
into v_num_assigned
from wf_task_assignments
where task_id = remove_task_assignment.task_id;
if v_num_assigned > 0 then
return;
end if;
-- yup, the task is now unassigned; fire the callback
open c_callback;
fetch c_callback into callback_rec;
if c_callback%FOUND then
execute_unassigned_callback (
callback => callback_rec.unassigned_callback,
task_id => task_id,
custom_arg => callback_rec.unassigned_custom_arg
);
end if;
close c_callback;
end remove_task_assignment;
procedure clear_task_assignments (
task_id in number,
permanent_p in char default 'f'
)
is
v_case_id number;
v_transition_key varchar2(100);
v_role_key wf_roles.role_key%TYPE;
v_workflow_key varchar2(100);
v_context_key varchar2(100);
v_callback varchar2(100);
v_custom_arg varchar2(4000);
begin
-- get some information
select ta.case_id, ta.transition_key, tr.role_key, ta.workflow_key, c.context_key
into v_case_id, v_transition_key, v_role_key, v_workflow_key, v_context_key
from wf_tasks ta, wf_transitions tr, wf_cases c
where ta.task_id = clear_task_assignments.task_id
and tr.workflow_key = ta.workflow_key
and tr.transition_key = ta.transition_key
and c.case_id = ta.case_id;
-- make the unassignment stick as a manual assignment
if permanent_p = 't' then
clear_manual_assignments(
case_id => v_case_id,
role_key => v_role_key
);
end if;
-- delete the rows
delete
from wf_task_assignments
where task_id = clear_task_assignments.task_id;
-- fire the unassigned callback
select unassigned_callback, unassigned_custom_arg
into v_callback, v_custom_arg
from wf_context_transition_info
where workflow_key = v_workflow_key
and context_key = v_context_key
and transition_key = v_transition_key;
execute_unassigned_callback(
callback => v_callback,
task_id => task_id,
custom_arg => v_custom_arg
);
end clear_task_assignments;
procedure set_case_deadline (
case_id in wf_cases.case_id%TYPE,
transition_key in wf_transitions.transition_key%TYPE,
deadline date
)
is
v_workflow_key wf_workflows.workflow_key%TYPE;
begin
-- delete the current deadline row
delete
from wf_case_deadlines
where case_id = set_case_deadline.case_id
and transition_key = set_case_deadline.transition_key;
if deadline is not null then
-- get some info
select workflow_key
into v_workflow_key
from wf_cases
where case_id = set_case_deadline.case_id;
-- insert new deadline row
insert into wf_case_deadlines (
case_id,
workflow_key,
transition_key,
deadline
) values (
set_case_deadline.case_id,
v_workflow_key,
set_case_deadline.transition_key,
set_case_deadline.deadline
);
end if;
end set_case_deadline;
procedure remove_case_deadline (
case_id in wf_cases.case_id%TYPE,
transition_key in wf_transitions.transition_key%TYPE
)
is
begin
set_case_deadline(
case_id => remove_case_deadline.case_id,
transition_key => remove_case_deadline.transition_key,
deadline => null
);
end remove_case_deadline;
/*
* PRIVATE
*/
function evaluate_guard (
callback in varchar2,
custom_arg in varchar2,
case_id in number,
workflow_key in varchar2,
transition_key in varchar2,
place_key in varchar2,
direction in varchar2
)
return char
is
v_guard_happy_p char(1);
begin
if callback is null then
-- null guard evaluates to true
return 't';
else
if callback = '#' then
return 'f';
else
execute immediate 'begin :1 := ' || callback
|| '(:2, :3, :4, :5, :6, :7); end;'
using out v_guard_happy_p,
in case_id,
in workflow_key,
in transition_key,
in place_key,
in direction,
in custom_arg;
return v_guard_happy_p;
end if;
end if;
end evaluate_guard;
procedure execute_transition_callback(
callback in varchar2,
custom_arg in varchar2,
case_id in number,
transition_key in varchar2
)
is
begin
if callback is not null then
execute immediate 'begin '||callback
|| '(:1, :2, :3); end;'
using in case_id,
in transition_key,
in custom_arg;
end if;
end execute_transition_callback;
function execute_time_callback (
callback in varchar2,
custom_arg in varchar2,
case_id in number,
transition_key in varchar2
)
return date
is
v_trigger_time date;
begin
if callback is null then
raise_application_error(-20000, 'There''s no time_callback function for the timed transition ''' || transition_key || '''');
end if;
execute immediate 'begin :1 := ' || callback
|| '(:2, :3, :4); end;'
using out v_trigger_time,
in case_id,
in transition_key,
in custom_arg;
return v_trigger_time;
end execute_time_callback;
function get_task_deadline (
callback in varchar2,
custom_arg in varchar2,
attribute_name in varchar2,
case_id in number,
transition_key in varchar2
)
return date
is
cursor case_deadline_cur is
select deadline
from wf_case_deadlines
where case_id = get_task_deadline.case_id
and transition_key = get_task_deadline.transition_key;
v_deadline date;
begin
/*
* 1. or if there's a row in wf_case_deadlines, we use that
* 2. if there is a callback, we execute that
* 3. otherwise, if there is an attribute, we use that
*/
/* wf_case_deadlines */
open case_deadline_cur;
fetch case_deadline_cur into v_deadline;
if case_deadline_cur%NOTFOUND then
if callback is not null then
/* callback */
execute immediate 'begin :1 := ' || callback
|| '(:2, :3, :4); end;'
using out v_deadline,
in case_id,
in transition_key,
in custom_arg;
elsif attribute_name is not null then
/* attribute */
v_deadline := acs_object.get_attribute(
object_id_in => get_task_deadline.case_id,
attribute_name_in => get_task_deadline.attribute_name
);
else
v_deadline := null;
end if;
end if;
return v_deadline;
end get_task_deadline;
function execute_hold_timeout_callback (
callback in varchar2,
custom_arg in varchar2,
case_id in number,
transition_key in varchar2
)
return date
is
v_hold_timeout date;
begin
if callback is null then
return null;
end if;
execute immediate 'begin :1 := ' || callback
|| '(:2, :3, :4); end;'
using out v_hold_timeout,
in case_id,
in transition_key,
in custom_arg;
return v_hold_timeout;
end execute_hold_timeout_callback;
procedure execute_unassigned_callback (
callback in varchar2,
task_id in number,
custom_arg in varchar2
)
is
begin
if callback is not null then
execute immediate 'begin ' || callback
|| '(:1, :2); end;'
using in task_id,
in custom_arg;
end if;
end execute_unassigned_callback;
procedure set_task_assignments(
task_id in number,
callback in varchar2,
custom_arg in varchar2
)
is
cursor case_assignments is
select party_id
from wf_case_assignments ca, wf_tasks t, wf_transitions tr
where t.task_id = set_task_assignments.task_id
and ca.case_id = t.case_id
and ca.role_key = tr.role_key
and tr.workflow_key = t.workflow_key
and tr.transition_key = t.transition_key;
cursor context_assignments is
select party_id
from wf_context_assignments ca, wf_cases c, wf_tasks t, wf_transitions tr
where t.task_id = set_task_assignments.task_id
and c.case_id = t.case_id
and ca.context_key = c.context_key
and ca.workflow_key = t.workflow_key
and ca.role_key = tr.role_key
and tr.workflow_key = t.workflow_key
and tr.transition_key = t.transition_key;
v_done_p char(1);
begin
/* Find out who to assign the given task to.
*
* 1. See if there are rows in wf_case_assignments.
* 2. If not, and a callback is defined, execute that.
* 3. Otherwise, grab the assignment from the workflow context.
*
* (We used to use the callback first, but that makes
* reassignment of tasks difficult.)
*/
v_done_p := 'f';
for case_assignment_rec in case_assignments loop
v_done_p := 't';
add_task_assignment (
task_id => task_id,
party_id => case_assignment_rec.party_id
);
end loop;
if v_done_p != 't' then
if callback is not null then
execute immediate 'begin '|| set_task_assignments.callback
|| '(:1, :2); end;'
using in set_task_assignments.task_id,
in set_task_assignments.custom_arg;
else
for context_assignment_rec in context_assignments loop
add_task_assignment (
task_id => task_id,
party_id => context_assignment_rec.party_id
);
end loop;
end if;
end if;
end set_task_assignments;
procedure add_token (
case_id in number,
place_key in varchar2,
journal_id in number
)
is
v_token_id number;
v_workflow_key varchar2(100);
begin
select wf_token_id_seq.nextval into v_token_id from dual;
select workflow_key into v_workflow_key
from wf_cases c
where c.case_id = add_token.case_id;
insert into wf_tokens
(token_id, case_id, workflow_key, place_key, state, produced_journal_id)
values
(v_token_id, add_token.case_id, v_workflow_key, add_token.place_key, 'free', add_token.journal_id);
end add_token;
procedure lock_token (
case_id in number,
place_key in varchar2,
journal_id in number,
task_id in number
)
is
begin
update wf_tokens
set state = 'locked',
locked_task_id = lock_token.task_id,
locked_date = sysdate,
locked_journal_id = lock_token.journal_id
where case_id = lock_token.case_id
and place_key = lock_token.place_key
and state = 'free'
and rownum = 1;
end lock_token;
procedure release_token (
task_id in number,
journal_id in number
)
is
cursor token_cur is
select token_id,
case_id,
place_key
from wf_tokens
where state = 'locked'
and locked_task_id = release_token.task_id;
begin
/* Add a new token for each released one */
for token_rec in token_cur loop
add_token(
case_id => token_rec.case_id,
place_key => token_rec.place_key,
journal_id => release_token.journal_id
);
end loop;
/* Mark the released ones canceled */
update wf_tokens
set state = 'canceled',
canceled_date = sysdate,
canceled_journal_id = release_token.journal_id
where state = 'locked'
and locked_task_id = release_token.task_id;
end release_token;
procedure consume_token (
case_id in number,
place_key in varchar2,
journal_id in number,
task_id in number default null
)
is
begin
if task_id is null then
update wf_tokens
set state = 'consumed',
consumed_date = sysdate,
consumed_journal_id = consume_token.journal_id
where case_id = consume_token.case_id
and place_key = consume_token.place_key
and state = 'free'
and rownum = 1;
else
update wf_tokens
set state = 'consumed',
consumed_date = sysdate,
consumed_journal_id = consume_token.journal_id
where case_id = consume_token.case_id
and place_key = consume_token.place_key
and state = 'locked'
and locked_task_id = consume_token.task_id;
end if;
end consume_token;
procedure sweep_automatic_transitions (
case_id in number,
journal_id in number
) is
cursor enabled_automatic_transitions is
select task_id
from wf_tasks ta, wf_transitions tr
where tr.workflow_key = ta.workflow_key
and tr.transition_key = ta.transition_key
and tr.trigger_type = 'automatic'
and ta.state = 'enabled'
and ta.case_id = sweep_automatic_transitions.case_id;
v_done_p char(1);
v_finished_p char(1);
begin
enable_transitions(case_id => sweep_automatic_transitions.case_id);
loop
v_done_p := 't';
v_finished_p := finished_p(
case_id => sweep_automatic_transitions.case_id,
journal_id => sweep_automatic_transitions.journal_id);
if v_finished_p = 'f' then
for task_rec in enabled_automatic_transitions loop
fire_transition_internal(
task_id => task_rec.task_id,
journal_id => sweep_automatic_transitions.journal_id
);
v_done_p := 'f';
end loop;
enable_transitions(case_id => sweep_automatic_transitions.case_id);
end if;
exit when v_done_p = 't';
end loop;
end sweep_automatic_transitions;
function finished_p (
case_id in number,
journal_id in number
)
return char
is
v_case_state varchar2(40);
v_token_id number;
v_num_rows number;
v_journal_id number;
begin
select state into v_case_state
from wf_cases
where case_id = finished_p.case_id;
if v_case_state = 'finished' then
return 't';
else
/* Let's see if the case is actually finished, but just not marked so */
select decode(count(*),0,0,1) into v_num_rows
from wf_tokens
where case_id = finished_p.case_id
and place_key = 'end';
if v_num_rows = 0 then
return 'f';
else
/* There's a token in the end place.
* Count the total number of tokens to make sure the wf is well-constructed.
*/
select decode(count(*),0,0,1,1,2) into v_num_rows
from wf_tokens
where case_id = finished_p.case_id
and state in ('free', 'locked');
if v_num_rows > 1 then
raise_application_error(-20000, 'The workflow net is misconstructed: Some parallel executions have not finished.');
end if;
/* Consume that token */
select token_id into v_token_id
from wf_tokens
where case_id = finished_p.case_id
and state in ('free', 'locked');
consume_token(
case_id => finished_p.case_id,
place_key => 'end',
journal_id => finished_p.journal_id
);
update wf_cases
set state = 'finished'
where case_id = finished_p.case_id;
/* Add an extra entry to the journal */
v_journal_id := journal_entry.new(
object_id => finished_p.case_id,
action => 'case finish',
action_pretty => 'Case finished'
);
return 't';
end if;
end if;
end finished_p;
/* This procedure should be scheduled to run as a dbms_job. */
procedure sweep_timed_transitions
is
cursor timed_transitions_to_fire is
select t.task_id, t.case_id, tr.transition_name
from wf_tasks t, wf_transitions tr
where trigger_time <= sysdate
and state = 'enabled'
and tr.workflow_key = t.workflow_key
and tr.transition_key = t.transition_key;
v_journal_id number;
begin
for trans_rec in timed_transitions_to_fire loop
/* Insert an entry to the journal so people will know it fired */
v_journal_id := journal_entry.new(
object_id => trans_rec.case_id,
action => 'task '||trans_rec.task_id|| ' fire time',
action_pretty => trans_rec.transition_name || ' automatically finished',
msg => 'Timed transition fired.'
);
/* Fire the transition */
fire_transition_internal(
task_id => trans_rec.task_id,
journal_id => v_journal_id
);
/* Update the workflow internal state */
sweep_automatic_transitions(
case_id => trans_rec.case_id,
journal_id => v_journal_id
);
end loop;
end sweep_timed_transitions;
/* This procedure should be scheduled to run as a dbms_job. */
procedure sweep_hold_timeout
is
cursor tasks_to_cancel is
select t.task_id, t.case_id, tr.transition_name
from wf_tasks t, wf_transitions tr
where hold_timeout <= sysdate
and state = 'started'
and tr.workflow_key = t.workflow_key
and tr.transition_key = t.transition_key;
v_journal_id number;
begin
for task_rec in tasks_to_cancel loop
/* Insert an entry to the journal so people will know it was canceled */
v_journal_id := journal_entry.new(
object_id => task_rec.case_id,
action => 'task '||task_rec.task_id||' cancel timeout',
action_pretty => task_rec.transition_name || ' timed out',
msg => 'The user''s hold on the task timed out and the task was automatically canceled'
);
/* Cancel the task */
cancel_task(
task_id => task_rec.task_id,
journal_id => v_journal_id
);
end loop;
end sweep_hold_timeout;
procedure notify_assignee(
task_id in wf_tasks.task_id%TYPE,
user_id in users.user_id%TYPE,
callback in wf_context_transition_info.notification_callback%TYPE,
custom_arg in wf_context_transition_info.notification_custom_arg%TYPE
)
is
v_deadline_pretty varchar2(400);
v_object_name varchar2(4000);
v_transition_key wf_transitions.transition_key%TYPE;
v_transition_name wf_transitions.transition_name%TYPE;
v_party_from parties.party_id%TYPE;
v_party_to parties.party_id%TYPE;
v_subject varchar2(4000);
v_body varchar2(4000);
v_request_id integer;
v_workflow_url varchar2(400);
cursor cr_principal is
select wfi.principal_party
from wf_context_workflow_info wfi, wf_tasks ta, wf_cases c
where ta.task_id = notify_assignee.task_id
and c.case_id = ta.case_id
and wfi.workflow_key = c.workflow_key
and wfi.context_key = c.context_key;
begin
select to_char(ta.deadline,'Mon fmDDfm, YYYY HH24:MI:SS'),
acs_object.name(c.object_id),
tr.transition_key,
tr.transition_name
into v_deadline_pretty,
v_object_name,
v_transition_key,
v_transition_name
from wf_tasks ta, wf_transitions tr, wf_cases c
where ta.task_id = notify_assignee.task_id
and c.case_id = ta.case_id
and tr.workflow_key = c.workflow_key
and tr.transition_key = ta.transition_key;
select apm.get_value(p.package_id,'SystemURL') || site_node.url(s.node_id)
into v_workflow_url
from site_nodes s,
apm_packages a,
(select package_id
from apm_packages
where package_key = 'acs-kernel') p
where s.object_id = a.package_id
and a.package_key = 'acs-workflow';
/* Mail sent from */
open cr_principal;
fetch cr_principal into v_party_from;
if cr_principal%NOTFOUND then
v_party_from := -1;
end if;
/* Subject */
v_subject := 'Assignment: '||v_transition_name||' ('||v_object_name||')';
/* Body */
v_body := 'You have been assigned to a task.
'||'
Case : '||v_object_name||'
Task : '||v_transition_name||'
';
if v_deadline_pretty != '' then
v_body := v_body||'Deadline : '||v_deadline_pretty||'
';
end if;
v_body := v_body ||'Task website: '||v_workflow_url||'task?task_id='||notify_assignee.task_id||'
';
/* The notifications should really be sent from the application server layer, not from the database */
if notify_assignee.callback is not null then
execute immediate 'begin '||notify_assignee.callback||'(:1, :2, :3, :4, :5, :6); end;'
using in notify_assignee.task_id,
in notify_assignee.custom_arg,
in notify_assignee.user_id,
in out v_party_from,
in out v_subject,
in out v_body;
else
v_request_id := acs_mail_nt.post_request (
party_from => v_party_from,
party_to => notify_assignee.user_id,
expand_group => 'f' ,
subject => v_subject,
message => v_body
);
end if;
end notify_assignee;
/*
* This procedure synchronizes the actually enabled transitions
* (i.e., the ones where tokens are currently present on the
* input places), with the cached version of that information,
* in wf_tasks.
* It is entirely idempotent and will at any given time sync up with
* the actual state of the workflow (as per the tokens), so we don't
* need to pass in a journal_id.
*/
procedure enable_transitions (
case_id in number
) is
cursor tasks_to_create is
select et.transition_key,
et.transition_name,
et.trigger_type,
et.enable_callback,
et.enable_custom_arg,
et.time_callback,
et.time_custom_arg,
et.deadline_callback,
et.deadline_custom_arg,
et.deadline_attribute_name,
et.notification_callback,
et.notification_custom_arg,
et.unassigned_callback,
et.unassigned_custom_arg,
et.estimated_minutes,
cr.assignment_callback,
cr.assignment_custom_arg
from wf_enabled_transitions et, wf_context_role_info cr
where et.case_id = enable_transitions.case_id
and et.workflow_key = cr.workflow_key (+)
and et.role_key = cr.role_key (+)
and not exists (select 1 from wf_tasks
where case_id = enable_transitions.case_id
and transition_key = et.transition_key
and state in ('enabled', 'started'));
v_task_id number;
v_workflow_key varchar2(100);
v_trigger_time date;
v_deadline_date date;
v_party_from integer;
v_subject varchar2(500);
v_body varchar2(4000);
v_num_assigned number;
request_id number;
cursor assignees_cur is
select distinct u.user_id
from wf_task_assignments tasgn,
party_approved_member_map m,
users u
where tasgn.task_id = v_task_id
and m.party_id = tasgn.party_id
and u.user_id = m.member_id;
begin
select workflow_key into v_workflow_key
from wf_cases
where case_id = enable_transitions.case_id;
/* we mark tasks overridden if they were once enabled, but are no longer so */
update wf_tasks
set state = 'overridden',
overridden_date = sysdate
where case_id = enable_transitions.case_id
and state = 'enabled'
and transition_key not in
(select transition_key
from wf_enabled_transitions
where case_id = enable_transitions.case_id);
/* insert a task for the transitions that are enabled but have no task row */
for trans_rec in tasks_to_create loop
v_trigger_time := null;
v_deadline_date := null;
if trans_rec.trigger_type = 'user' then
v_deadline_date := get_task_deadline(
callback => trans_rec.deadline_callback,
custom_arg => trans_rec.deadline_custom_arg,
attribute_name => trans_rec.deadline_attribute_name,
case_id => enable_transitions.case_id,
transition_key => trans_rec.transition_key
);
elsif trans_rec.trigger_type = 'time' then
v_trigger_time := execute_time_callback(trans_rec.time_callback,
trans_rec.time_custom_arg,
enable_transitions.case_id, trans_rec.transition_key);
end if;
/* we're ready to insert the row */
select wf_task_id_seq.nextval into v_task_id from dual;
insert into wf_tasks (
task_id, case_id, workflow_key, transition_key,
deadline, trigger_time, estimated_minutes
) values (
v_task_id, enable_transitions.case_id, v_workflow_key,
trans_rec.transition_key,
v_deadline_date, v_trigger_time, trans_rec.estimated_minutes
);
set_task_assignments(
task_id => v_task_id,
callback => trans_rec.assignment_callback,
custom_arg => trans_rec.assignment_custom_arg
);
/* Execute the transition enabled callback */
execute_transition_callback(
callback => trans_rec.enable_callback,
custom_arg => trans_rec.enable_custom_arg,
case_id => enable_transitions.case_id,
transition_key => trans_rec.transition_key
);
select count(*) into v_num_assigned
from wf_task_assignments
where task_id = v_task_id;
if v_num_assigned = 0 then
execute_unassigned_callback (
callback => trans_rec.unassigned_callback,
task_id => v_task_id,
custom_arg => trans_rec.unassigned_custom_arg
);
end if;
end loop;
end enable_transitions;
procedure fire_transition_internal (
task_id in number,
journal_id in number
) is
v_case_id number;
v_state varchar2(40);
v_transition_key varchar2(100);
v_workflow_key varchar2(100);
v_place_key varchar2(100);
v_direction varchar2(3);
v_guard_happy_p char(1);
v_fire_callback varchar2(100);
v_fire_custom_arg varchar2(4000);
v_found_happy_guard char(1);
v_locked_task_id number;
begin
select t.case_id, t.state, t.workflow_key, t.transition_key, ti.fire_callback, ti.fire_custom_arg
into v_case_id, v_state, v_workflow_key, v_transition_key, v_fire_callback, v_fire_custom_arg
from wf_tasks t, wf_cases c, wf_transition_info ti
where t.task_id = fire_transition_internal.task_id
and c.case_id = t.case_id
and ti.context_key = c.context_key
and ti.workflow_key = c.workflow_key
and ti.transition_key = t.transition_key;
/* Check that the state is either started or enabled */
if v_state = 'enabled' then
v_locked_task_id := null;
elsif v_state = 'started' then
v_locked_task_id := fire_transition_internal.task_id;
else
raise_application_error(-20000, 'Can''t fire the transition if it''s not in state enabled or started');
end if;
/* Mark the task finished */
update wf_tasks
set state = 'finished',
finished_date = sysdate
where task_id = fire_transition_internal.task_id;
/* Consume the tokens */
for place_rec in input_places(v_workflow_key, v_transition_key) loop
consume_token(
case_id => v_case_id,
place_key => place_rec.place_key,
journal_id => fire_transition_internal.journal_id,
task_id => v_locked_task_id
);
end loop;
/* Spit out new tokens in the output places */
v_found_happy_guard := 'f';
for place_rec in output_places(v_workflow_key, v_transition_key) loop
v_place_key := place_rec.place_key;
v_direction := place_rec.direction;
v_guard_happy_p := evaluate_guard(
callback => place_rec.guard_callback,
custom_arg => place_rec.guard_custom_arg,
case_id => v_case_id,
workflow_key => v_workflow_key,
transition_key => v_transition_key,
place_key => v_place_key,
direction => v_direction
);
if v_guard_happy_p = 't' then
v_found_happy_guard := 't';
add_token(
case_id => v_case_id,
place_key => place_rec.place_key,
journal_id => fire_transition_internal.journal_id
);
end if;
end loop;
/* If we didn't find any happy guards, look for arcs with the special hash (#) guard */
if v_found_happy_guard = 'f' then
for place_rec in (
select place_key
from wf_transition_places tp
where tp.workflow_key = v_workflow_key
and tp.transition_key = v_transition_key
and tp.direction = 'out'
and tp.guard_callback = '#')
loop
add_token(
case_id => v_case_id,
place_key => place_rec.place_key,
journal_id => fire_transition_internal.journal_id
);
end loop;
end if;
/* Execute the transition fire callback */
execute_transition_callback(
callback => v_fire_callback,
custom_arg => v_fire_custom_arg,
case_id => v_case_id,
transition_key => v_transition_key
);
end fire_transition_internal;
/* A small helper to make sure we're in the state we expect to be */
procedure ensure_task_in_state (
task_id in number,
state in varchar2
) is
v_count number;
begin
select decode(count(*),0,0,1) into v_count
from wf_tasks
where task_id = ensure_task_in_state.task_id
and state = ensure_task_in_state.state;
if v_count != 1 then
raise_application_error(-20000, 'The task '|| ensure_task_in_state.task_id || ' is not in state ''' || ensure_task_in_state.state || '''');
end if;
end ensure_task_in_state;
/* Marks a task started and reserves one token from each input place */
procedure start_task(
task_id in number,
user_id in number,
journal_id in number
) is
v_case_id number;
v_workflow_key wf_workflows.workflow_key%TYPE;
v_transition_key varchar2(100);
v_hold_timeout_callback varchar2(100);
v_hold_timeout_custom_arg varchar2(4000);
v_hold_timeout date;
begin
ensure_task_in_state(task_id => start_task.task_id, state => 'enabled');
select t.case_id, t.workflow_key, t.transition_key, ti.hold_timeout_callback, ti.hold_timeout_custom_arg
into v_case_id, v_workflow_key, v_transition_key, v_hold_timeout_callback, v_hold_timeout_custom_arg
from wf_tasks t, wf_cases c, wf_transition_info ti
where t.task_id = start_task.task_id
and c.case_id = t.case_id
and ti.context_key = c.context_key
and ti.workflow_key = t.workflow_key
and ti.transition_key = t.transition_key;
v_hold_timeout := execute_hold_timeout_callback(v_hold_timeout_callback,
v_hold_timeout_custom_arg, v_case_id, v_transition_key);
/* Mark it started */
update wf_tasks
set state = 'started',
started_date = sysdate,
holding_user = start_task.user_id,
hold_timeout = v_hold_timeout
where task_id = start_task.task_id;
/* Reserve one token from each input place */
for place_rec in input_places(v_workflow_key,v_transition_key) loop
lock_token(
case_id => v_case_id,
place_key => place_rec.place_key,
journal_id => start_task.journal_id,
task_id => start_task.task_id
);
end loop;
end start_task;
/* Mark the task canceled and release the reserved tokens */
procedure cancel_task(
task_id in number,
journal_id in number
)
is
v_case_id number;
begin
ensure_task_in_state(task_id => cancel_task.task_id, state => 'started');
select case_id into v_case_id
from wf_tasks
where task_id = cancel_task.task_id;
/* Mark the task canceled */
update wf_tasks
set state = 'canceled',
canceled_date = sysdate
where task_id = cancel_task.task_id;
/* Release our reserved tokens */
release_token(
task_id => cancel_task.task_id,
journal_id => cancel_task.journal_id
);
/* The workflow state has now changed, so we must run this */
sweep_automatic_transitions(
case_id => v_case_id,
journal_id => cancel_task.journal_id
);
end cancel_task;
/* Fire the transition */
procedure finish_task (
task_id in number,
journal_id in number
)
is
v_case_id number;
begin
select case_id into v_case_id
from wf_tasks
where task_id = finish_task.task_id;
fire_transition_internal(
task_id => finish_task.task_id,
journal_id => finish_task.journal_id
);
sweep_automatic_transitions(
case_id => v_case_id,
journal_id => finish_task.journal_id
);
end finish_task;
function get_task_id (
case_id in wf_cases.case_id%TYPE,
transition_key in wf_transitions.transition_key%TYPE
) return wf_tasks.task_id%TYPE
is
v_task_id number;
begin
select task_id into v_task_id
from wf_tasks
where case_id = get_task_id.case_id and
transition_key = get_task_id.transition_key;
return v_task_id;
exception when no_data_found then
raise_application_error(-20000, 'Case ' || case_id || 'has no transition with key ' || transition_key);
end get_task_id;
end workflow_case;
/
show errors;
acs-workflow-master/sql/oracle/workflow-case-package-head.sql 0000664 0000000 0000000 00000011211 14575002472 0024627 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/workflow-case-package-head.sql
--
-- Creates the PL/SQL package that provides the API for interacting
-- with a workflow case.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
create or replace package workflow_case
is
function new (
case_id in number default null,
workflow_key in varchar2,
context_key in varchar2 default null,
object_id in integer,
creation_date in date default sysdate,
creation_user in integer default null,
creation_ip in varchar2 default null
) return integer;
procedure add_manual_assignment (
case_id in number,
role_key in varchar2,
party_id in number
);
procedure remove_manual_assignment (
case_id in number,
role_key in varchar2,
party_id in number
);
procedure clear_manual_assignments (
case_id in number,
role_key in varchar2
);
procedure start_case (
case_id in number,
creation_user in integer default null,
creation_ip in varchar2 default null,
msg in varchar2 default null
);
procedure del (
case_id in number
);
procedure suspend(
case_id in number,
user_id in number default null,
ip_address in varchar2 default null,
msg in varchar2 default null
);
procedure resume(
case_id in number,
user_id in number default null,
ip_address in varchar2 default null,
msg in varchar2 default null
);
procedure cancel(
case_id in number,
user_id in number default null,
ip_address in varchar2 default null,
msg in varchar2 default null
);
procedure fire_message_transition (
task_id in number
);
/* To perform an action on the workflow:
* (numbers in parenthesis is the number of times each function should get called)
*
* 1. begin_task_action (1) (returns journal_id)
* 2. set_attribute_value (0..*)
* 3. clear_manual_assignments (0..1)
* 4. add_manual_assignment (0..*)
* 5. end_task_action (1)
*/
function begin_task_action (
task_id in number,
action in varchar2,
action_ip in varchar2,
user_id in number,
msg in varchar2 default null
) return number;
procedure set_attribute_value (
journal_id in number,
attribute_name in varchar2,
value in varchar2
);
procedure end_task_action (
journal_id in number,
action in varchar2,
task_id in number
);
/* Shortcut, that does both begin and end, when you have no attributes to set or assignments to make */
function task_action (
task_id in number,
action in varchar2,
action_ip in varchar2,
user_id in number,
msg in varchar2 default null
) return number;
function get_attribute_value (
case_id in number,
attribute_name in varchar2
) return varchar2;
procedure add_task_assignment (
task_id in number,
party_id in number,
permanent_p in char default 'f'
);
procedure remove_task_assignment (
task_id in number,
party_id in number,
permanent_p in char default 'f'
);
procedure clear_task_assignments (
task_id in number,
permanent_p in char default 'f'
);
procedure set_case_deadline (
case_id in wf_cases.case_id%TYPE,
transition_key in wf_transitions.transition_key%TYPE,
deadline date
);
procedure remove_case_deadline (
case_id in wf_cases.case_id%TYPE,
transition_key in wf_transitions.transition_key%TYPE
);
-- DRB: I added this function because there appeared to be no way for a
-- client to get the task_id without querying the wf_tasks table directly,
-- breaking the PL/SQL abstraction.
function get_task_id (
case_id in wf_cases.case_id%TYPE,
transition_key in wf_transitions.transition_key%TYPE
) return wf_tasks.task_id%TYPE;
/* DBMS_JOBS */
procedure sweep_timed_transitions;
procedure sweep_hold_timeout;
end workflow_case;
/
show errors;
acs-workflow-master/sql/oracle/workflow-case-package.sql 0000664 0000000 0000000 00000000463 14575002472 0023737 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/workflow-case-package.sql
--
-- Creates the PL/SQL package that provides the API for interacting
-- with a workflow case.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
@@workflow-case-package-head.sql
@@workflow-case-package-body.sql
acs-workflow-master/sql/oracle/workflow-package-body.sql 0000664 0000000 0000000 00000060540 14575002472 0023763 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/workflow-package-head.sql
--
-- Creates the PL/SQL package that provides the API for defining and dropping
-- workflow cases.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
create or replace package body workflow
as
function create_workflow (
workflow_key in varchar2,
pretty_name in varchar2,
pretty_plural in varchar2 default null,
description in varchar2 default null,
table_name in varchar2,
id_column in varchar2 default 'case_id'
)
return varchar2
is
v_num_rows number;
v_workflow_key varchar2(100);
begin
select count(*) into v_num_rows from user_tables where table_name = upper(create_workflow.table_name);
if v_num_rows = 0 then
raise_application_error(-20000, 'The table '''||create_workflow.table_name||''' must be created before calling workflow.create_workflow.');
end if;
if substr(create_workflow.workflow_key, length(create_workflow.workflow_key) - 2, 3) != '_wf' then
v_workflow_key := create_workflow.workflow_key||'_wf';
else
v_workflow_key := create_workflow.workflow_key;
end if;
acs_object_type.create_type(
object_type => v_workflow_key,
pretty_name => create_workflow.pretty_name,
pretty_plural => create_workflow.pretty_plural,
supertype => 'workflow',
table_name => create_workflow.table_name,
id_column => create_workflow.id_column
);
insert into wf_workflows
(workflow_key, description)
values
(v_workflow_key, create_workflow.description);
return v_workflow_key;
end create_workflow;
/* Note: The workflow-specific cases table must be dropped before calling this proc */
procedure drop_workflow (
workflow_key in varchar2
)
is
v_table_name varchar2(100);
v_num_rows number;
cursor attribute_cur is
select attribute_id, attribute_name from acs_attributes where object_type = drop_workflow.workflow_key;
begin
select table_name into v_table_name
from acs_object_types
where object_type = drop_workflow.workflow_key;
select decode(count(*),0,0,1) into v_num_rows
from user_tables
where table_name = upper(v_table_name);
if v_num_rows > 0 then
raise_application_error(-20000, 'The table '''||v_table_name||''' must be dropped before calling workflow.drop_workflow.');
end if;
select decode(count(*),0,0,1) into v_num_rows
from wf_cases
where workflow_key = drop_workflow.workflow_key;
if v_num_rows > 0 then
raise_application_error(-20000, 'You must delete all cases of workflow '''||drop_workflow.workflow_key||''' before dropping the workflow definition.');
end if;
/* Delete all the auxillary stuff */
delete from wf_context_task_panels where workflow_key = drop_workflow.workflow_key;
delete from wf_context_assignments where workflow_key = drop_workflow.workflow_key;
delete from wf_context_role_info where workflow_key = drop_workflow.workflow_key;
delete from wf_context_transition_info where workflow_key = drop_workflow.workflow_key;
delete from wf_context_workflow_info where workflow_key = drop_workflow.workflow_key;
delete from wf_arcs where workflow_key = drop_workflow.workflow_key;
delete from wf_places where workflow_key = drop_workflow.workflow_key;
delete from wf_transition_role_assign_map where workflow_key = drop_workflow.workflow_key;
delete from wf_transitions where workflow_key = drop_workflow.workflow_key;
delete from wf_roles where workflow_key = drop_workflow.workflow_key;
/* Drop all attributes */
for attribute_rec in attribute_cur loop
/* there's no on delete cascade, so we have to manually delete all the values */
delete from acs_attribute_values where attribute_id = attribute_rec.attribute_id;
drop_attribute(
workflow_key => drop_workflow.workflow_key,
attribute_name => attribute_rec.attribute_name
);
end loop;
/* Delete the workflow */
delete from wf_workflows where workflow_key = drop_workflow.workflow_key;
acs_object_type.drop_type(
object_type => drop_workflow.workflow_key
);
end drop_workflow;
procedure delete_cases (
workflow_key in varchar2
)
is
cursor workflow_cases is select case_id from wf_cases where workflow_key = delete_cases.workflow_key;
begin
for case_rec in workflow_cases loop
workflow_case.del(case_rec.case_id);
end loop;
end delete_cases;
function create_attribute (
workflow_key in varchar2,
attribute_name in varchar2,
datatype in varchar2,
pretty_name in varchar2,
pretty_plural in varchar2 default null,
table_name in varchar2 default null,
column_name in varchar2 default null,
default_value in varchar2 default null,
min_n_values in integer default 1,
max_n_values in integer default 1,
sort_order in integer default null,
storage in varchar2 default 'generic'
) return acs_attributes.attribute_id%TYPE
is
v_attribute_id number;
begin
v_attribute_id := acs_attribute.create_attribute(
object_type => create_attribute.workflow_key,
attribute_name => create_attribute.attribute_name,
datatype => create_attribute.datatype,
pretty_name => create_attribute.pretty_name,
pretty_plural => create_attribute.pretty_plural,
table_name => create_attribute.table_name,
column_name => create_attribute.column_name,
default_value => create_attribute.default_value,
min_n_values => create_attribute.min_n_values,
max_n_values => create_attribute.max_n_values,
sort_order => create_attribute.sort_order,
storage => create_attribute.storage
);
return v_attribute_id;
end create_attribute;
procedure drop_attribute (
workflow_key in varchar2,
attribute_name in varchar2
)
is
v_attribute_id number;
begin
select attribute_id into v_attribute_id
from acs_attributes
where object_type = drop_attribute.workflow_key
and attribute_name = drop_attribute.attribute_name;
acs_attribute.drop_attribute(
object_type => drop_attribute.workflow_key,
attribute_name => drop_attribute.attribute_name
);
end drop_attribute;
procedure add_place (
workflow_key in acs_object_types.object_type%TYPE,
place_key in wf_places.place_key%TYPE,
place_name in wf_places.place_name%TYPE,
sort_order in wf_places.sort_order%TYPE default null
)
is
v_sort_order wf_places.sort_order%TYPE;
begin
if add_place.sort_order is null then
select nvl(max(sort_order)+1, 1)
into v_sort_order
from wf_places
where workflow_key = add_place.workflow_key;
else
v_sort_order := add_place.sort_order;
end if;
insert into wf_places (workflow_key, place_key, place_name, sort_order)
values (add_place.workflow_key, add_place.place_key, add_place.place_name, v_sort_order);
end add_place;
procedure delete_place (
workflow_key in acs_object_types.object_type%TYPE,
place_key in wf_places.place_key%TYPE
)
is
begin
delete from wf_places
where workflow_key = delete_place.workflow_key
and place_key = delete_place.place_key;
end delete_place;
procedure add_role (
workflow_key in acs_object_types.object_type%TYPE,
role_key in wf_roles.role_key%TYPE,
role_name in wf_roles.role_name%TYPE,
sort_order in wf_roles.sort_order%TYPE default null
)
is
v_sort_order wf_roles.sort_order%TYPE;
begin
if add_role.sort_order is null then
select nvl(max(sort_order)+1, 1)
into v_sort_order
from wf_roles
where workflow_key = add_role.workflow_key;
else
v_sort_order := add_role.sort_order;
end if;
insert into wf_roles (
workflow_key, role_key, role_name, sort_order
) values (
add_role.workflow_key, add_role.role_key, add_role.role_name, v_sort_order
);
end add_role;
procedure move_role_up(
workflow_key in acs_object_types.object_type%TYPE,
role_key in wf_roles.role_key%TYPE
)
is
v_this_sort_order wf_roles.sort_order%TYPE;
v_prior_sort_order wf_roles.sort_order%TYPE;
cursor c_prior_sort_order is
select max(sort_order)
from wf_roles
where workflow_key = move_role_up.workflow_key
and sort_order < v_this_sort_order;
begin
select sort_order
into v_this_sort_order
from wf_roles
where workflow_key = move_role_up.workflow_key
and role_key = move_role_up.role_key;
open c_prior_sort_order;
fetch c_prior_sort_order into v_prior_sort_order;
if c_prior_sort_order%NOTFOUND then
/* already at top of sort order */
return;
end if;
/* switch the sort orders around */
update wf_roles
set sort_order = decode(role_key, move_role_up.role_key, v_prior_sort_order, v_this_sort_order)
where workflow_key = move_role_up.workflow_key
and sort_order in (v_this_sort_order, v_prior_sort_order);
end move_role_up;
procedure move_role_down(
workflow_key in acs_object_types.object_type%TYPE,
role_key in wf_roles.role_key%TYPE
)
is
v_this_sort_order wf_roles.sort_order%TYPE;
v_next_sort_order wf_roles.sort_order%TYPE;
cursor c_next_sort_order is
select min(sort_order)
from wf_roles
where workflow_key = move_role_down.workflow_key
and sort_order > v_this_sort_order;
begin
select sort_order
into v_this_sort_order
from wf_roles
where workflow_key = move_role_down.workflow_key
and role_key = move_role_down.role_key;
open c_next_sort_order;
fetch c_next_sort_order into v_next_sort_order;
if c_next_sort_order%NOTFOUND then
/* already at bottom of sort order */
return;
end if;
/* switch the sort orders around */
update wf_roles
set sort_order = decode(role_key, move_role_down.role_key, v_next_sort_order, v_this_sort_order)
where workflow_key = move_role_down.workflow_key
and sort_order in (v_this_sort_order, v_next_sort_order);
end move_role_down;
procedure delete_role (
workflow_key in acs_object_types.object_type%TYPE,
role_key in wf_roles.role_key%TYPE
)
is
begin
/* First, remove all references to this role from transitions */
update wf_transitions
set role_key = null
where workflow_key = delete_role.workflow_key
and role_key = delete_role.role_key;
delete from wf_roles
where workflow_key = delete_role.workflow_key
and role_key = delete_role.role_key;
end delete_role;
procedure add_transition (
workflow_key in acs_object_types.object_type%TYPE,
transition_key in wf_transitions.transition_key%TYPE,
transition_name in wf_transitions.transition_name%TYPE,
role_key in wf_roles.role_key%TYPE default null,
sort_order in wf_transitions.sort_order%TYPE default null,
trigger_type in wf_transitions.trigger_type%TYPE default 'user'
)
is
v_sort_order wf_transitions.sort_order%TYPE;
begin
if add_transition.sort_order is null then
select nvl(max(sort_order)+1, 1)
into v_sort_order
from wf_transitions
where workflow_key = add_transition.workflow_key;
else
v_sort_order := add_transition.sort_order;
end if;
insert into wf_transitions (
workflow_key,
transition_key,
transition_name,
role_key,
sort_order,
trigger_type
) values (
add_transition.workflow_key,
add_transition.transition_key,
add_transition.transition_name,
add_transition.role_key,
v_sort_order,
add_transition.trigger_type
);
end add_transition;
procedure delete_transition (
workflow_key in acs_object_types.object_type%TYPE,
transition_key in wf_transitions.transition_key%TYPE
)
is
begin
delete from wf_transitions
where workflow_key = delete_transition.workflow_key
and transition_key = delete_transition.transition_key;
end delete_transition;
procedure add_arc (
workflow_key in acs_object_types.object_type%TYPE,
transition_key in wf_arcs.transition_key%TYPE,
place_key in wf_arcs.place_key%TYPE,
direction in wf_arcs.direction%TYPE,
guard_callback in wf_arcs.guard_callback%TYPE default null,
guard_custom_arg in wf_arcs.guard_custom_arg%TYPE default null,
guard_description in wf_arcs.guard_description%TYPE default null
)
is
begin
insert into wf_arcs (workflow_key, transition_key, place_key, direction,
guard_callback, guard_custom_arg, guard_description)
values (add_arc.workflow_key, add_arc.transition_key, add_arc.place_key, add_arc.direction,
add_arc.guard_callback, add_arc.guard_custom_arg, add_arc.guard_description);
end add_arc;
procedure add_arc (
workflow_key in acs_object_types.object_type%TYPE,
from_transition_key in wf_arcs.transition_key%TYPE,
to_place_key in wf_arcs.place_key%TYPE,
guard_callback in wf_arcs.guard_callback%TYPE default null,
guard_custom_arg in wf_arcs.guard_custom_arg%TYPE default null,
guard_description in wf_arcs.guard_description%TYPE default null
)
is
begin
add_arc(
workflow_key => add_arc.workflow_key,
transition_key => add_arc.from_transition_key,
place_key => add_arc.to_place_key,
direction => 'out',
guard_callback => add_arc.guard_callback,
guard_custom_arg => add_arc.guard_custom_arg,
guard_description => add_arc.guard_description
);
end add_arc;
procedure add_arc (
workflow_key in acs_object_types.object_type%TYPE,
from_place_key in wf_arcs.place_key%TYPE,
to_transition_key in wf_arcs.transition_key%TYPE
)
is
begin
add_arc(
workflow_key => add_arc.workflow_key,
place_key => add_arc.from_place_key,
transition_key => add_arc.to_transition_key,
direction => 'in'
);
end add_arc;
procedure delete_arc (
workflow_key in acs_object_types.object_type%TYPE,
transition_key in wf_arcs.transition_key%TYPE,
place_key in wf_arcs.place_key%TYPE,
direction in wf_arcs.direction%TYPE
)
is
begin
delete from wf_arcs
where workflow_key = delete_arc.workflow_key
and transition_key = delete_arc.transition_key
and place_key = delete_arc.place_key
and direction = delete_arc.direction;
end delete_arc;
procedure add_trans_attribute_map(
workflow_key in wf_workflows.workflow_key%TYPE,
transition_key in wf_transitions.transition_key%TYPE,
attribute_id in acs_attributes.attribute_id%TYPE,
sort_order in wf_transition_attribute_map.sort_order%TYPE default null
)
is
v_num_rows integer;
v_sort_order wf_transition_attribute_map.sort_order%TYPE;
begin
select count(*)
into v_num_rows
from wf_transition_attribute_map
where workflow_key = add_trans_attribute_map.workflow_key
and transition_key = add_trans_attribute_map.transition_key
and attribute_id = add_trans_attribute_map.attribute_id;
if v_num_rows > 0 then
return;
end if;
if add_trans_attribute_map.sort_order is null then
select nvl(max(sort_order)+1, 1)
into v_sort_order
from wf_transition_attribute_map
where workflow_key = add_trans_attribute_map.workflow_key
and transition_key = add_trans_attribute_map.transition_key;
else
v_sort_order := add_trans_attribute_map.sort_order;
end if;
insert into wf_transition_attribute_map (
workflow_key,
transition_key,
attribute_id,
sort_order
) values (
add_trans_attribute_map.workflow_key,
add_trans_attribute_map.transition_key,
add_trans_attribute_map.attribute_id,
v_sort_order
);
end add_trans_attribute_map;
procedure add_trans_attribute_map(
workflow_key in wf_workflows.workflow_key%TYPE,
transition_key in wf_transitions.transition_key%TYPE,
attribute_name in acs_attributes.attribute_name%TYPE,
sort_order in wf_transition_attribute_map.sort_order%TYPE default null
)
is
v_attribute_id integer;
begin
select attribute_id
into v_attribute_id
from acs_attributes
where object_type = add_trans_attribute_map.workflow_key
and attribute_name = add_trans_attribute_map.attribute_name;
add_trans_attribute_map(
workflow_key => add_trans_attribute_map.workflow_key,
transition_key => add_trans_attribute_map.transition_key,
attribute_id => v_attribute_id,
sort_order => add_trans_attribute_map.sort_order
);
end add_trans_attribute_map;
procedure delete_trans_attribute_map(
workflow_key in wf_workflows.workflow_key%TYPE,
transition_key in wf_transitions.transition_key%TYPE,
attribute_id in acs_attributes.attribute_id%TYPE
)
is
begin
delete
from wf_transition_attribute_map
where workflow_key = delete_trans_attribute_map.workflow_key
and transition_key = delete_trans_attribute_map.transition_key
and attribute_id = delete_trans_attribute_map.attribute_id;
end delete_trans_attribute_map;
procedure delete_trans_attribute_map(
workflow_key in wf_workflows.workflow_key%TYPE,
transition_key in wf_transitions.transition_key%TYPE,
attribute_name in acs_attributes.attribute_id%TYPE
)
is
v_attribute_id integer;
begin
select attribute_id
into v_attribute_id
from acs_attributes
where object_type = delete_trans_attribute_map.workflow_key
and attribute_name = delete_trans_attribute_map.attribute_name;
delete
from wf_transition_attribute_map
where workflow_key = delete_trans_attribute_map.workflow_key
and transition_key = delete_trans_attribute_map.transition_key
and attribute_id = v_attribute_id;
end delete_trans_attribute_map;
procedure add_trans_role_assign_map(
workflow_key in wf_workflows.workflow_key%TYPE,
transition_key in wf_transitions.transition_key%TYPE,
assign_role_key in wf_roles.role_key%TYPE
)
is
v_num_rows integer;
begin
select count(*)
into v_num_rows
from wf_transition_role_assign_map
where workflow_key = add_trans_role_assign_map.workflow_key
and transition_key = add_trans_role_assign_map.transition_key
and assign_role_key = add_trans_role_assign_map.assign_role_key;
if v_num_rows = 0 then
insert into wf_transition_role_assign_map (
workflow_key,
transition_key,
assign_role_key
) values (
add_trans_role_assign_map.workflow_key,
add_trans_role_assign_map.transition_key,
add_trans_role_assign_map.assign_role_key
);
end if;
end add_trans_role_assign_map;
procedure delete_trans_role_assign_map(
workflow_key in wf_workflows.workflow_key%TYPE,
transition_key in wf_transitions.transition_key%TYPE,
assign_role_key in wf_roles.role_key%TYPE
)
is
begin
delete
from wf_transition_role_assign_map
where workflow_key = delete_trans_role_assign_map.workflow_key
and transition_key = delete_trans_role_assign_map.transition_key
and assign_role_key = delete_trans_role_assign_map.assign_role_key;
end delete_trans_role_assign_map;
function simple_p (
workflow_key in varchar2
)
return char
is
type t_place_table is table of wf_places.place_key%TYPE
index by binary_integer;
type t_guard_table is table of wf_arcs.guard_callback%TYPE
index by binary_integer;
previous_place_list t_place_table;
target_place_list t_place_table;
guard_list t_guard_table;
row_count integer := 0;
v_count integer;
v_count2 integer;
v_place_key wf_places.place_key%TYPE;
v_end_place wf_places.place_key%TYPE;
v_transition_key wf_transitions.transition_key%TYPE;
cursor transition_targets is
select place_key,guard_callback,rownum
from wf_arcs
where workflow_key = simple_p.workflow_key
and transition_key = v_transition_key
and direction = 'out';
begin
/* Let's do some simple checks first */
/* Places with more than one arc out */
select count(*) into v_count
from wf_places p
where p.workflow_key = simple_p.workflow_key
and 1 < (select count(*)
from wf_arcs a
where a.workflow_key = p.workflow_key
and a.place_key = p.place_key
and direction = 'in');
if v_count > 0 then
return 'f';
end if;
/* Transitions with more than one arc in */
select count(*) into v_count
from wf_transitions t
where t.workflow_key = simple_p.workflow_key
and 1 < (select count(*)
from wf_arcs a
where a.workflow_key = t.workflow_key
and a.transition_key = t.transition_key
and direction = 'in');
if v_count > 0 then
return 'f';
end if;
/* Transitions with more than two arcs out */
select count(*) into v_count
from wf_transitions t
where t.workflow_key = simple_p.workflow_key
and 2 < (select count(*)
from wf_arcs a
where a.workflow_key = t.workflow_key
and a.transition_key = t.transition_key
and direction = 'out');
if v_count > 0 then
return 'f';
end if;
/* Now we do the more complicated checks.
* We keep a list of visited places because I couldn't think
* of a nicer way that wasn't susceptable to infinite loops.
*/
v_place_key := 'start';
v_end_place := 'end';
loop
exit when v_place_key = v_end_place;
previous_place_list(row_count) := v_place_key;
select unique transition_key into v_transition_key
from wf_arcs
where workflow_key = simple_p.workflow_key
and place_key = v_place_key
and direction = 'in';
select count(*) into v_count
from wf_arcs
where workflow_key = simple_p.workflow_key
and transition_key = v_transition_key
and direction = 'out';
if v_count = 1 then
select unique place_key into v_place_key
from wf_arcs
where workflow_key = simple_p.workflow_key
and transition_key = v_transition_key
and direction = 'out';
elsif v_count = 0 then
/* deadend! */
return 'f';
else
/* better be two based on our earlier test */
for v_target in transition_targets loop
target_place_list(v_target.rownum) := v_target.place_key;
guard_list(v_target.rownum) := v_target.guard_callback;
end loop;
/* Check that the guard functions are the negation of each other
* by looking for the magic entry "#" (exactly once)
*/
if ((guard_list(1) != '#' and guard_list(2) != '#') or
(guard_list(1) = '#' and guard_list(2) = '#')) then
return 'f';
end if;
/* Check that exactly one of the targets is in the previous list */
v_count2 := 0;
for i in 0..row_count loop
if target_place_list(1) = previous_place_list(i) then
v_count2 := v_count2 + 1;
v_place_key := target_place_list(2);
end if;
if target_place_list(2) = previous_place_list(i) then
v_count2 := v_count2 + 1;
v_place_key := target_place_list(1);
end if;
end loop;
if v_count2 != 1 then
return 'f';
end if;
end if;
row_count := row_count + 1;
end loop;
/* if we got here, it must be okay */
return 't';
end simple_p;
end workflow;
/
show errors
acs-workflow-master/sql/oracle/workflow-package-head.sql 0000664 0000000 0000000 00000014162 14575002472 0023726 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/workflow-package-head.sql
--
-- Creates the PL/SQL package that provides the API for defining and dropping
-- workflow cases.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
create or replace package workflow
as
/* Call this function after you have created a table */
function create_workflow (
workflow_key in varchar2,
pretty_name in varchar2,
pretty_plural in varchar2 default null,
description in varchar2 default null,
table_name in varchar2,
id_column in varchar2 default 'case_id'
) return varchar2;
procedure drop_workflow (
workflow_key in varchar2
);
procedure delete_cases (
workflow_key in varchar2
);
function create_attribute (
workflow_key in varchar2,
attribute_name in varchar2,
datatype in varchar2,
pretty_name in varchar2,
pretty_plural in varchar2 default null,
table_name in varchar2 default null,
column_name in varchar2 default null,
default_value in varchar2 default null,
min_n_values in integer default 1,
max_n_values in integer default 1,
sort_order in integer default null,
storage in varchar2 default 'generic'
) return acs_attributes.attribute_id%TYPE;
procedure drop_attribute (
workflow_key in varchar2,
attribute_name in varchar2
);
procedure add_place (
workflow_key in acs_object_types.object_type%TYPE,
place_key in wf_places.place_key%TYPE,
place_name in wf_places.place_name%TYPE,
sort_order in wf_places.sort_order%TYPE default null
);
procedure delete_place (
workflow_key in acs_object_types.object_type%TYPE,
place_key in wf_places.place_key%TYPE
);
procedure add_role (
workflow_key in acs_object_types.object_type%TYPE,
role_key in wf_roles.role_key%TYPE,
role_name in wf_roles.role_name%TYPE,
sort_order in wf_roles.sort_order%TYPE default null
);
procedure move_role_up(
workflow_key in acs_object_types.object_type%TYPE,
role_key in wf_roles.role_key%TYPE
);
procedure move_role_down(
workflow_key in acs_object_types.object_type%TYPE,
role_key in wf_roles.role_key%TYPE
);
procedure delete_role (
workflow_key in acs_object_types.object_type%TYPE,
role_key in wf_roles.role_key%TYPE
);
procedure add_transition (
workflow_key in acs_object_types.object_type%TYPE,
transition_key in wf_transitions.transition_key%TYPE,
transition_name in wf_transitions.transition_name%TYPE,
role_key in wf_roles.role_key%TYPE default null,
sort_order in wf_transitions.sort_order%TYPE default null,
trigger_type in wf_transitions.trigger_type%TYPE default 'user'
);
procedure delete_transition (
workflow_key in acs_object_types.object_type%TYPE,
transition_key in wf_transitions.transition_key%TYPE
);
procedure add_arc (
workflow_key in acs_object_types.object_type%TYPE,
transition_key in wf_arcs.transition_key%TYPE,
place_key in wf_arcs.place_key%TYPE,
direction in wf_arcs.direction%TYPE,
guard_callback in wf_arcs.guard_callback%TYPE default null,
guard_custom_arg in wf_arcs.guard_custom_arg%TYPE default null,
guard_description in wf_arcs.guard_description%TYPE default null
);
procedure add_arc (
workflow_key in acs_object_types.object_type%TYPE,
from_transition_key in wf_arcs.transition_key%TYPE,
to_place_key in wf_arcs.place_key%TYPE,
guard_callback in wf_arcs.guard_callback%TYPE default null,
guard_custom_arg in wf_arcs.guard_custom_arg%TYPE default null,
guard_description in wf_arcs.guard_description%TYPE default null
);
procedure add_arc (
workflow_key in acs_object_types.object_type%TYPE,
from_place_key in wf_arcs.place_key%TYPE,
to_transition_key in wf_arcs.transition_key%TYPE
);
procedure delete_arc (
workflow_key in acs_object_types.object_type%TYPE,
transition_key in wf_arcs.transition_key%TYPE,
place_key in wf_arcs.place_key%TYPE,
direction in wf_arcs.direction%TYPE
);
procedure add_trans_attribute_map(
workflow_key in wf_workflows.workflow_key%TYPE,
transition_key in wf_transitions.transition_key%TYPE,
attribute_id in acs_attributes.attribute_id%TYPE,
sort_order in wf_transition_attribute_map.sort_order%TYPE default null
);
procedure add_trans_attribute_map(
workflow_key in wf_workflows.workflow_key%TYPE,
transition_key in wf_transitions.transition_key%TYPE,
attribute_name in acs_attributes.attribute_name%TYPE,
sort_order in wf_transition_attribute_map.sort_order%TYPE default null
);
procedure delete_trans_attribute_map(
workflow_key in wf_workflows.workflow_key%TYPE,
transition_key in wf_transitions.transition_key%TYPE,
attribute_id in acs_attributes.attribute_id%TYPE
);
procedure add_trans_role_assign_map(
workflow_key in wf_workflows.workflow_key%TYPE,
transition_key in wf_transitions.transition_key%TYPE,
assign_role_key in wf_roles.role_key%TYPE
);
procedure delete_trans_role_assign_map(
workflow_key in wf_workflows.workflow_key%TYPE,
transition_key in wf_transitions.transition_key%TYPE,
assign_role_key in wf_roles.role_key%TYPE
);
/*
* A simple workflow is essentially one that we can display nicely using HTML tables.
* More specifically, it's a workflow containing only sequential routing and
* simple iteration, where the choice is always between moving to the next task
* in the sequence or looping back to some prior task.
*/
function simple_p (
workflow_key in varchar2
) return char;
end workflow;
/
show errors
acs-workflow-master/sql/oracle/workflow-package.sql 0000664 0000000 0000000 00000000455 14575002472 0023027 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/workflow-package-head.sql
--
-- Creates the PL/SQL package that provides the API for defining and dropping
-- workflow cases.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
@@workflow-package-head.sql
@@workflow-package-body.sql
acs-workflow-master/sql/postgresql/ 0000775 0000000 0000000 00000000000 14575002472 0017775 5 ustar 00root root 0000000 0000000 acs-workflow-master/sql/postgresql/acs-workflow-create.sql 0000664 0000000 0000000 00000000676 14575002472 0024406 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/acs-workflow-create.sql
--
-- Calls the other SQL files to create the data models and PL/SQL packages.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
/* We create two sample processes */
\i wf-core-create.sql
\i workflow-case-package.sql
\i workflow-package.sql
\i wf-callback-package.sql
-- \i jobs-start.sql
-- \i sample-expenses-create.sql
\i sample-article-create.sql
acs-workflow-master/sql/postgresql/acs-workflow-drop.sql 0000664 0000000 0000000 00000001166 14575002472 0024102 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/acs-workflow-drop.sql
--
-- Drops the data model and the PL/SQL packages.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
--\i jobs-kill.sql
\i sample-article-drop.sql
\i wf-core-drop.sql
drop function __workflow__simple_p (varchar,integer);
drop table guard_list;
drop table target_place_list;
drop table previous_place_list;
drop sequence workflow_session_id;
drop function sweep_hold_timeout ();
drop function sweep_timed_transitions ();
select drop_package('wf_callback');
select drop_package('workflow');
select drop_package('workflow_case');
acs-workflow-master/sql/postgresql/load-workflow.sql 0000664 0000000 0000000 00000011537 14575002472 0023314 0 ustar 00root root 0000000 0000000
create function my_random()
returns integer as $$
begin
return random();
end;$$ language 'plpgsql';
-- show errors
create function push_task_ahead(integer,varchar,integer,varchar,varchar)
returns integer as $$
declare
push_task_ahead__task_id alias for $1;
push_task_ahead__state alias for $2;
push_task_ahead__user_id alias for $3;
push_task_ahead__workflow_key alias for $4;
push_task_ahead__transition_key alias for $5;
v_journal_id integer;
v_value char(1);
attr_rec record;
begin
if state = 'enabled' then
v_journal_id := workflow_case__task_action (
push_task_ahead__task_id,
'start',
'1.1.1.1',
push_task_ahead__user_id,
null
);
else
/* State must be started */
if my_random() < 0.02 then
v_journal_id := workflow_case__task_action (
push_task_ahead__task_id,
'cancel',
'1.1.1.1',
push_task_ahead__user_id,
null
);
else
v_journal_id := workflow_case__begin_task_action (
push_task_ahead__task_id,
'finish',
'1.1.1.1',
push_task_ahead__user_id,
null
);
for attr_rec in select a.attribute_name, datatype
from wf_transition_attribute_map m, acs_attributes a
where workflow_key = push_task_ahead.workflow_key
and transition_key = push_task_ahead.transition_key
and a.attribute_id = m.attribute_id
loop
/* We only know how to handle boolean attributes ...
but that's the only thing we have right now, so ... */
if attr_rec.datatype = 'boolean' then
if my_random() < 0.5 then
v_value := 't';
else
v_value := 'f';
end if;
select workflow_case__set_attribute_value (
v_journal_id,
attr_rec.attribute_name,
v_value
);
end if;
end loop;
select workflow_case__end_task_action (
v_journal_id,
'finish',
push_task_ahead__task_id
);
end if;
end if;
return 0;
end;$$ language 'plpgsql';
select inline_1 ();
drop function inline_1 ();
create function inline_2 ()
returns integer as $$
declare
v_object_id integer;
v_workflow_key varchar(100);
v_count integer;
v_num_cases integer;
v_party_id integer;
v_case_id integer;
v_task_id integer;
v_user_id integer;
v_num_tasks integer;
v_state varchar(100);
v_transition_key varchar(100);
trans_rec record;
party_rec record;
case_rec record;
begin
v_num_cases := 100;
--select dbms_random__initialize (943820482);
-- );
for trans_rec in select transition_key
from wf_transitions
where workflow_key = v_workflow_key
LOOP
for party_rec in select party_id
from parties sample(50)
LOOP
select workflow_case__add_manual_assignment (
v_case_id,
trans_rec.transition_key,
party_rec.party_id
);
end loop;
end loop;
select workflow_case__start_case (
v_case_id,
null,
null,
null
);
end loop;
/* Move 85% of the cases all the way to finished */
for case_rec in select case_id from wf_cases sample (85)
loop
loop
select case when count(*) = 0 then 0 else 1 end into v_num_tasks
from wf_user_tasks;
exit when v_num_tasks = 0;
if my_random() < 0.005 then
select workflow_case__cancel (
case_rec.case_id,
null,
null,
null
);
end if;
select task_id, state, user_id, workflow_key, transition_key
into v_task_id, v_state, v_user_id, v_workflow_key, v_transition_key
from wf_user_tasks
where case_id = case_rec.case_id
and rownum = 1;
PERFORM push_task_ahead(
v_task_id,
v_state,
v_user_id,
v_workflow_key,
v_transition_key
);
end loop;
end loop;
/* Fire transitions at random */
for v_count in 1 .. round(v_num_cases * 0.15 * 3)
loop
select case when count(*) = 0 then 0 else 1 end into v_num_tasks
from wf_user_tasks;
exit when v_num_tasks = 0;
select task_id, state, user_id, workflow_key, transition_key
into v_task_id, v_state, v_user_id, v_workflow_key, v_transition_key
from wf_user_tasks
limit 1;
PERFORM push_task_ahead(
v_task_id,
v_state,
v_user_id,
v_workflow_key,
v_transition_key
);
end loop;
return 0;
end;$$ language 'plpgsql';
select inline_2 ();
drop function inline_2 ();
acs-workflow-master/sql/postgresql/sample-article-create.sql 0000664 0000000 0000000 00000016545 14575002472 0024674 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/sample-article-create.sql
--
-- Creates a sample article-authoring workflow to play with
--
-- @author Kevin Scaldeferri (kevin@theory.caltech.edu)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
/* This table will hold one row for each case using this workflow. */
create table wf_article_cases (
case_id integer primary key
constraint wf_article_cases_case_fk
references wf_cases on delete cascade
);
create function inline_0 () returns integer as $$
declare
v_workflow_key wf_workflows.workflow_key%TYPE;
v_attribute_id acs_attributes.attribute_id%TYPE;
begin
v_workflow_key := workflow__create_workflow(
'article_wf',
'Article Publication',
'Article Publications',
'Workflow for managing the publication of an article',
'wf_article_cases',
'case_id'
);
/*****
* Places
*****/
perform workflow__add_place(
'article_wf',
'start',
'Start place',
1
);
perform workflow__add_place(
'article_wf',
'to_be_written',
'Needs to be written',
2
);
perform workflow__add_place(
'article_wf',
'to_be_reviewed',
'Needs review',
3
);
perform workflow__add_place(
'article_wf',
'to_be_published',
'Ready to go to press',
4
);
perform workflow__add_place(
'article_wf',
'end',
'End place',
5
);
/*****
* Roles
*****/
perform workflow__add_role(
'article_wf',
'author',
'Author',
1
);
perform workflow__add_role(
'article_wf',
'editor',
'Editor',
2
);
/*****
* Transitions
*****/
perform workflow__add_transition(
'article_wf',
'specify',
'Describe task and assign author',
'editor',
1,
'user'
);
perform workflow__add_transition(
'article_wf',
'write',
'Write article',
'author',
2,
'user'
);
perform workflow__add_transition(
'article_wf',
'review',
'Review article',
'editor',
3,
'user'
);
perform workflow__add_transition(
'article_wf',
'publish',
'Publish article',
null,
4,
'automatic'
);
/*****
* Arcs
*****/
perform workflow__add_arc(
'article_wf',
'start',
'specify'
);
perform workflow__add_arc(
'article_wf',
'specify',
'to_be_written',
null,
null,
null
);
perform workflow__add_arc(
'article_wf',
'to_be_written',
'write'
);
perform workflow__add_arc(
'article_wf',
'write',
'to_be_reviewed',
null,
null,
null
);
perform workflow__add_arc(
'article_wf',
'to_be_reviewed',
'review'
);
perform workflow__add_arc(
'article_wf',
'review',
'to_be_published',
'wf_callback__guard_attribute_true',
'reviewer_ok',
'Reviewer approved article'
);
perform workflow__add_arc(
'article_wf',
'review',
'to_be_written',
'#',
null,
'Reviewer did not approve article'
);
perform workflow__add_arc(
'article_wf',
'to_be_published',
'publish'
);
perform workflow__add_arc(
'article_wf',
'publish',
'end',
null,
null,
null
);
/*****
* Attributes
*****/
v_attribute_id := workflow__create_attribute(
'article_wf',
'reviewer_ok',
'boolean',
'Reviewer Approval',
null,
null,
null,
'f',
1,
1,
null,
'generic'
);
perform workflow__add_trans_attribute_map(
'article_wf',
'review',
'reviewer_ok',
1
);
/*****
* Assignment
*****/
perform workflow__add_trans_role_assign_map(
'article_wf',
'specify',
'author'
);
return 0;
end;$$ language 'plpgsql';
select inline_0 ();
drop function inline_0 ();
/* Context stuff */
insert into wf_context_transition_info (
context_key,
workflow_key,
transition_key,
hold_timeout_callback,
hold_timeout_custom_arg
) values (
'default',
'article_wf',
'specify',
'wf_callback__time_sysdate_plus_x',
1/24
);
-- create or replace package body wf_article_callback
-- FIXME: last three variables are in/out variables.
create function wf_article_callback__notification(integer,varchar,integer,integer,varchar,varchar)
returns integer as $$
declare
notification__task_id alias for $1;
notification__custom_arg alias for $2;
notification__party_to alias for $3;
notification__party_from alias for $4;
notification__subject alias for $5;
notification__body alias for $6;
v_deadline_pretty varchar(400);
v_object_name text;
v_transition_name wf_transitions.transition_name%TYPE;
v_name varchar(1000);
v_subject text default '';
v_body text default '';
v_request_id integer;
begin
select to_char(ta.deadline,'Mon fmDDfm, YYYY HH24:MI:SS'),
acs_object__name(c.object_id),
tr.transition_name
into v_deadline_pretty,
v_object_name,
v_transition_name
from wf_tasks ta, wf_transitions tr, wf_cases c
where ta.task_id = notification__task_id
and c.case_id = ta.case_id
and tr.workflow_key = c.workflow_key
and tr.transition_key = ta.transition_key;
v_subject := 'Assignment: ' || v_transition_name || ' ' ||
v_object_name;
v_body := 'Dear ' || acs_object__name(notification__party_to) || '
' || '
Today, you have been assigned to a task.
' || '
Task : ' || v_transition_name || '
Object : ' || v_object_name || '
';
if v_deadline_pretty != '' then
v_body := v_body || 'Deadline: ' || v_deadline_pretty || '
';
end if;
-- NOTICE, NOTICE, NOTICE
--
-- Since postgresql does not support out parameters, this
-- function call has been moved from workflow_case.notify_assignee
-- into the callback function.
-- If you implement a new notification callback, make sure
-- that this function call is included at the end of the
-- callback routine just as we have done for this example code.
--
-- DanW (dcwickstrom@earthlink.net)
v_request_id := acs_mail_nt__post_request (
notification__party_from, -- party_from
notification__party_to, -- party_to
'f', -- expand_group
v_subject, -- subject
v_body, -- message
0 -- max_retries
);
return null;
end;$$ language 'plpgsql';
update wf_context_transition_info
set notification_callback = 'wf_article_callback__notification'
where workflow_key = 'article_wf'
and context_key = 'default'
and transition_key = 'specify';
acs-workflow-master/sql/postgresql/sample-article-drop.sql 0000664 0000000 0000000 00000001326 14575002472 0024364 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/sample-article-drop.sql
--
-- Drops the article-authoring workflow.
--
-- @author Kevin Scaldeferri (kevin@theory.caltech.edu)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
create function inline_0 () returns integer as $$
begin
perform workflow__delete_cases('article_wf');
return 0;
end;$$ language 'plpgsql';
drop table wf_article_cases;
select inline_0 ();
drop function inline_0 ();
create function inline_0 () returns integer as $$
begin
perform workflow__drop_workflow('article_wf');
return 0;
end;$$ language 'plpgsql';
select inline_0 ();
drop function inline_0 ();
drop function wf_article_callback__notification(integer,varchar,integer,integer,varchar,varchar);
acs-workflow-master/sql/postgresql/sample-expenses-create.sql 0000664 0000000 0000000 00000025751 14575002472 0025102 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/sample-expenses-create.sql
--
-- Creates an expenses workflow to play with.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
/* This table will hold one row for each case using this workflow. */
create table wf_expenses_cases (
case_id integer primary key
constraint wf_expenses_cases_case_fk
references wf_cases on delete cascade
);
declare
v_workflow_key wf_workflows.workflow_key%TYPE;
v_attribute_id acs_attributes.attribute_id%TYPE;
begin
v_workflow_key := workflow.create_workflow(
workflow_key => 'expenses_wf',
pretty_name => 'Expense Authorization',
pretty_plural => 'Expense authorizations',
description => 'Workflow for authorizing employee''s expenses on the company''s behalf',
table_name => 'wf_expenses_cases'
);
/*****
* Places
*****/
workflow.add_place(
workflow_key => 'expenses_wf',
place_key => 'start',
place_name => 'Start place',
sort_order => 1
);
workflow.add_place(
workflow_key => 'expenses_wf',
place_key => 'assignments_done',
place_name => 'Tasks have been assigned',
sort_order => 2
);
workflow.add_place(
workflow_key => 'expenses_wf',
place_key => 'supervisor_to_approve',
place_name => 'Supervisor is to approve',
sort_order => 3
);
workflow.add_place(
workflow_key => 'expenses_wf',
place_key => 'other_to_approve',
place_name => 'Other is to approve',
sort_order => 4
);
workflow.add_place(
workflow_key => 'expenses_wf',
place_key => 'supervisor_approved',
place_name => 'Supervisor has approved',
sort_order => 5
);
workflow.add_place(
workflow_key => 'expenses_wf',
place_key => 'other_approved',
place_name => 'Other has approved',
sort_order => 6
);
workflow.add_place(
workflow_key => 'expenses_wf',
place_key => 'ready_to_buy',
place_name => 'Both have approved',
sort_order => 7
);
workflow.add_place(
workflow_key => 'expenses_wf',
place_key => 'end',
place_name => 'End place',
sort_order => 8
);
/*****
* Roles
*****/
workflow.add_role(
workflow_key => 'expenses_wf',
role_key => 'assignor',
role_name => 'Assignor',
sort_order => 1
);
workflow.add_role(
workflow_key => 'expenses_wf',
role_key => 'supervisor',
role_name => 'Supervisor',
sort_order => 2
);
workflow.add_role(
workflow_key => 'expenses_wf',
role_key => 'other',
role_name => 'Other approver',
sort_order => 3
);
workflow.add_role(
workflow_key => 'expenses_wf',
role_key => 'requestor',
role_name => 'Requestor',
sort_order => 4
);
/*****
* Transitions
*****/
workflow.add_transition(
workflow_key => 'expenses_wf',
transition_key => 'assign',
transition_name => 'Assign users to approval',
role_key => 'assignor',
sort_order => 1,
trigger_type => 'user'
);
workflow.add_transition(
workflow_key => 'expenses_wf',
transition_key => 'and_split',
transition_name => 'Parallel approval by supervisor and other',
sort_order => 2,
trigger_type => 'automatic'
);
workflow.add_transition(
workflow_key => 'expenses_wf',
transition_key => 'supervisor_approval',
transition_name => 'Approve (Supervisor)',
role_key => 'supervisor',
sort_order => 3,
trigger_type => 'user'
);
workflow.add_transition(
workflow_key => 'expenses_wf',
transition_key => 'other_approval',
transition_name => 'Approve (Other)',
role_key => 'other',
sort_order => 4,
trigger_type => 'user'
);
workflow.add_transition(
workflow_key => 'expenses_wf',
transition_key => 'and_join',
transition_name => 'Re-synchronization from approval by supervisor and other',
sort_order => 5,
trigger_type => 'automatic'
);
workflow.add_transition(
workflow_key => 'expenses_wf',
transition_key => 'buy',
transition_name => 'Buy stuff',
role_key => 'requestor',
sort_order => 6,
trigger_type => 'user'
);
/*****
* Arcs
*****/
workflow.add_arc(
workflow_key => 'expenses_wf',
from_place_key => 'start',
to_transition_key => 'assign'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_transition_key => 'assign',
to_place_key => 'assignments_done'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_place_key => 'assignments_done',
to_transition_key => 'and_split'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_transition_key => 'and_split',
to_place_key => 'supervisor_to_approve'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_transition_key => 'and_split',
to_place_key => 'other_to_approve'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_place_key => 'supervisor_to_approve',
to_transition_key => 'supervisor_approval'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_transition_key => 'supervisor_approval',
to_place_key => 'supervisor_approved'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_place_key => 'other_to_approve',
to_transition_key => 'other_approval'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_transition_key => 'other_approval',
to_place_key => 'other_approved'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_place_key => 'supervisor_approved',
to_transition_key => 'and_join'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_place_key => 'other_approved',
to_transition_key => 'and_join'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_transition_key => 'and_join',
to_place_key => 'ready_to_buy',
guard_callback => 'wf_expenses.guard_both_approved_p',
guard_description => 'Both Supervisor and the Other approver approved'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_transition_key => 'and_join',
to_place_key => 'end',
guard_callback => '#',
guard_description => 'Either Supervisor or the Other approver did not approve'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_place_key => 'ready_to_buy',
to_transition_key => 'buy'
);
workflow.add_arc(
workflow_key => 'expenses_wf',
from_transition_key => 'buy',
to_place_key => 'end'
);
/*****
* Attributes
*****/
v_attribute_id := workflow.create_attribute(
workflow_key => 'expenses_wf',
attribute_name => 'supervisor_ok',
datatype => 'boolean',
pretty_name => 'Supervisor Approval',
default_value => 'f',
sort_order => 1
);
workflow.add_trans_attribute_map(
workflow_key => 'expenses_wf',
transition_key => 'supervisor_approval',
attribute_name => 'supervisor_ok',
sort_order => 1
);
v_attribute_id := workflow.create_attribute(
workflow_key => 'expenses_wf',
attribute_name => 'other_ok',
datatype => 'boolean',
pretty_name => 'Other Approval',
default_value => 'f',
sort_order => 2
);
workflow.add_trans_attribute_map(
workflow_key => 'expenses_wf',
transition_key => 'other_approval',
attribute_name => 'other_ok',
sort_order => 1
);
/*****
* Assignment
*****/
workflow.add_trans_role_assign_map(
workflow_key => 'expenses_wf',
transition_key => 'assign',
assign_role_key => 'supervisor'
);
workflow.add_trans_role_assign_map(
workflow_key => 'expenses_wf',
transition_key => 'assign',
assign_role_key => 'other'
);
end;
/
show errors
/* Context stuff */
insert into wf_context_transition_info (
context_key, workflow_key, transition_key, estimated_minutes
) values (
'default', 'expenses_wf', 'assign', 5
);
insert into wf_context_transition_info (
context_key, workflow_key, transition_key, hold_timeout_callback, hold_timeout_custom_arg, estimated_minutes
) values (
'default', 'expenses_wf', 'supervisor_approval', 'wf_callback.time_sysdate_plus_x', 1/24, 15
);
insert into wf_context_transition_info (
context_key, workflow_key, transition_key, estimated_minutes
) values (
'default', 'expenses_wf', 'other_approval', 15
);
insert into wf_context_transition_info (
context_key, workflow_key, transition_key, estimated_minutes
) values (
'default', 'expenses_wf', 'buy', 30
);
insert into wf_context_task_panels (
context_key, workflow_key, transition_key, sort_order, header, template_url
) values (
'default', 'expenses_wf', 'supervisor_approval', 1, 'Claim Info', 'sample/expenses-claim-info'
);
insert into wf_context_task_panels (
context_key, workflow_key, transition_key, sort_order, header, template_url
) values (
'default', 'expenses_wf', 'supervisor_approval', 2, 'Logic and Aids', 'sample/expenses-approval-aids'
);
insert into wf_context_task_panels (
context_key, workflow_key, transition_key, sort_order, header, template_url
) values (
'default', 'expenses_wf', 'other_approval', 1, 'Claim Info', 'sample/expenses-claim-info'
);
insert into wf_context_task_panels (
context_key, workflow_key, transition_key, sort_order, header, template_url
) values (
'default', 'expenses_wf', 'other_approval', 2, 'Logic and Aids', 'sample/expenses-approval-aids'
);
commit;
/* Callbacks for the workflow */
create or replace package wf_expenses
is
function guard_both_approved_p (
case_id in number,
workflow_key in varchar2,
transition_key in varchar2,
place_key in varchar2,
direction_in varchar2,
custom_arg in varchar2
)
return char;
end wf_expenses;
/
show errors;
create or replace package body wf_expenses
is
function guard_both_approved_p (
case_id in number,
workflow_key in varchar2,
transition_key in varchar2,
place_key in varchar2,
direction_in varchar2,
custom_arg in varchar2
)
return char
is
v_other_ok_p char(1);
v_supervisor_ok_p char(1);
begin
v_other_ok_p := workflow_case.get_attribute_value(
case_id => guard_both_approved_p.case_id,
attribute_name => 'other_ok'
);
if v_other_ok_p = 'f' then
return 'f';
end if;
v_supervisor_ok_p := workflow_case.get_attribute_value(
case_id => guard_both_approved_p.case_id,
attribute_name => 'supervisor_ok'
);
return v_supervisor_ok_p;
end guard_both_approved_p;
end wf_expenses;
/
show errors;
acs-workflow-master/sql/postgresql/sample-expenses-drop.sql 0000664 0000000 0000000 00000000576 14575002472 0024601 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/sample-expenses-drop.sql
--
-- Drops the expenses workflow.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
begin
workflow.delete_cases(workflow_key => 'expenses_wf');
end;
/
show errors;
drop table wf_expenses_cases;
begin
workflow.drop_workflow(workflow_key => 'expenses_wf');
end;
/
show errors;
acs-workflow-master/sql/postgresql/test/ 0000775 0000000 0000000 00000000000 14575002472 0020754 5 ustar 00root root 0000000 0000000 acs-workflow-master/sql/postgresql/test/workflow-case-package-test.sql 0000664 0000000 0000000 00000030550 14575002472 0026631 0 ustar 00root root 0000000 0000000 -- set serveroutput on size 1000000 format wrapped
-- requires the utPLSQL system
--
-- modify this line to suit your needs
--
-- exec utplsql.setdir('/web/lars-dev2/packages/acs-kernel/sql');
-- exec utplsql.autocompile (false);
-- create or replace package ut#workflow_case
-- as
--
-- procedure setup;
--
-- procedure teardown;
--
-- procedure run;
--
-- end ut#workflow_case;
-- /
-- show errors
-- create or replace package body ut#workflow_case
create function utassert__eq(varchar,integer,integer) returns integer as '
declare
v_msg alias for $1;
v_in alias for $2;
v_chk alias for $3;
begin
if v_in != v_chk then
raise NOTICE ''%: failed'', v_msg;
end if;
return null;
end;' language 'plpgsql';
create function utassert__eq(varchar,text,text) returns integer as '
declare
v_msg alias for $1;
v_in alias for $2;
v_chk alias for $3;
begin
if v_in != v_chk then
raise NOTICE ''%: failed'', v_msg;
end if;
return null;
end;' language 'plpgsql';
create function setup() returns integer as '
declare
wf_count integer;
exists_p boolean;
begin
PERFORM teardown();
raise NOTICE ''Setting up...'';
/* We assume that the sample-expenses workflow is loaded and
unchanged from the original */
select count(*) > 0 into exists_p
from pg_proc
where proname = ''acs_mail_nt__post_request'';
if NOT exists_p then
execute ''create function acs_mail_nt__post_request(integer,integer,boolean,text,text,integer) returns integer as \\\'
begin
return null;
end;\\\' language \\\'plpgsql\\\''';
end if;
select case when count(*) = 0 then 0 else 1 end
into wf_count
from wf_workflows
where workflow_key = ''expenses_wf'';
if wf_count = 0 then
raise EXCEPTION ''-20000: The sample-expenses workflow must be loaded (and unchanged from the original)'';
end if;
return null;
end;' language 'plpgsql';
create function teardown() returns integer as '
begin
raise NOTICE ''Tearing down...'';
return null;
end;' language 'plpgsql';
create function run() returns integer as '
declare
v_workflow_key wf_workflows.workflow_key%TYPE;
v_object_id acs_objects.object_id%TYPE;
v_case_id wf_cases.case_id%TYPE;
v_count integer;
v_task_id integer;
v_journal_id integer;
v_user_id integer;
v_state varchar(100);
begin
v_workflow_key := ''expenses_wf'';
PERFORM acs_user__new(
null,
''user'',
now(),
null,
''127.0.0.1'',
''jane.doe@arsdigita.com'',
null,
''Jane'',
''Doe'',
''janedoerules'',
null,
null,
null,
null,
''t'',
null
);
raise NOTICE ''Running test...'';
/* Pick out a random object ... we just hope there is one somewhere */
select object_id into v_object_id
from acs_objects
limit 1;
raise NOTICE ''. new case'';
v_case_id := workflow_case__new(
null,
v_workflow_key,
''default'',
v_object_id,
now(),
null,
null
);
raise NOTICE ''. manual assignments'';
/* we need a random user_id */
select user_id into v_user_id
from users
limit 1;
PERFORM workflow_case__add_manual_assignment (
v_case_id,
''assign'',
v_user_id
);
PERFORM workflow_case__add_manual_assignment (
v_case_id,
''supervisor_approval'',
v_user_id
);
PERFORM workflow_case__add_manual_assignment (
v_case_id,
''other_approval'',
v_user_id
);
PERFORM workflow_case__add_manual_assignment (
v_case_id,
''buy'',
v_user_id
);
raise NOTICE ''. start case'';
PERFORM workflow_case__start_case(
v_case_id,
null,
null,
null
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id
and transition_key = ''assign''
and state = ''enabled'';
PERFORM utassert__eq(
''We should have exactly one "assign" task enabled'',
1,
v_count
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id;
PERFORM utassert__eq(
''The "assign" task should be the only task there is for this case yet.'',
1,
v_count
);
/* Get that task_id */
select task_id into v_task_id
from wf_tasks
where case_id = v_case_id
and transition_key = ''assign''
and state = ''enabled'';
raise NOTICE ''. start task "assign"'';
v_journal_id := workflow_case__begin_task_action(
v_task_id,
''start'',
''0.0.0.0'',
v_user_id,
''regression-test: started task "assign"''
);
PERFORM workflow_case__end_task_action(
v_journal_id,
''start'',
v_task_id
);
select state into v_state
from wf_tasks
where task_id = v_task_id;
PERFORM utassert__eq(
''The "assign" task should be in state "started".'',
''started'',
v_state
);
raise NOTICE ''. cancel task "assign"'';
v_journal_id := workflow_case__begin_task_action(
v_task_id,
''cancel'',
''0.0.0.0'',
v_user_id,
''regression-test: canceled task "assign"''
);
PERFORM workflow_case__end_task_action(
v_journal_id,
''cancel'',
v_task_id
);
select state into v_state
from wf_tasks
where task_id = v_task_id;
PERFORM utassert__eq(
''The "assign" task should be in state "canceled".'',
''canceled'',
v_state
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id
and transition_key = ''assign''
and state = ''enabled'';
PERFORM utassert__eq(
''We should have exactly one "assign" task enabled'',
1,
v_count
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id;
PERFORM utassert__eq(
''There should be exactly two tasks for this case, one enabled and one canceled.'',
2,
v_count
);
raise NOTICE ''. finish task "assign"'';
/* Get that task_id for the assign task */
select task_id into v_task_id
from wf_tasks
where case_id = v_case_id
and transition_key = ''assign''
and state = ''enabled'';
v_journal_id := workflow_case__begin_task_action(
v_task_id,
''finish'',
''0.0.0.0'',
v_user_id,
''regression-test: finished task "assign"''
);
PERFORM workflow_case__end_task_action(
v_journal_id,
''finish'',
v_task_id
);
select state into v_state
from wf_tasks
where task_id = v_task_id;
PERFORM utassert__eq(
''The "assign" task should be in state "finished".'',
''finished'',
v_state
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id
and transition_key = ''supervisor_approval''
and state = ''enabled'';
PERFORM utassert__eq(
''We should have exactly one "supervisor_approval" task enabled'',
1,
v_count
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id
and transition_key = ''other_approval''
and state = ''enabled'';
PERFORM utassert__eq(
''We should have exactly one "other_approval" task enabled'',
1,
v_count
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id;
PERFORM utassert__eq(
''There should be exactly five tasks for this case, one canceled, two finished, and two enabled.'',
5,
v_count
);
raise NOTICE ''. finish task "supervisor_approval" without starting it first (saying okay)'';
/* Get the task_id for the supervisor_approval task */
select task_id into v_task_id
from wf_tasks
where case_id = v_case_id
and transition_key = ''supervisor_approval''
and state = ''enabled'';
v_journal_id := workflow_case__begin_task_action(
v_task_id,
''finish'',
''0.0.0.0'',
v_user_id,
''regression-test: finished task "supervisor_approval"''
);
PERFORM workflow_case__set_attribute_value(
v_journal_id,
''supervisor_ok'',
''t''
);
PERFORM workflow_case__end_task_action(
v_journal_id,
''finish'',
v_task_id
);
select state into v_state
from wf_tasks
where task_id = v_task_id;
PERFORM utassert__eq(
''The "supervisor_approval" task should be in state "finished".'',
''finished'',
v_state
);
raise NOTICE ''. finish task "other_approval" without starting it first (saying okay)'';
/* Get the task_id for the other_approval task */
select task_id into v_task_id
from wf_tasks
where case_id = v_case_id
and transition_key = ''other_approval''
and state = ''enabled'';
v_journal_id := workflow_case__begin_task_action(
v_task_id,
''finish'',
''0.0.0.0'',
v_user_id,
''regression-test: finished task "other_approval"''
);
PERFORM workflow_case__set_attribute_value(
v_journal_id,
''other_ok'',
''t''
);
PERFORM workflow_case__end_task_action(
v_journal_id,
''finish'',
v_task_id
);
select state into v_state
from wf_tasks
where task_id = v_task_id;
PERFORM utassert__eq(
''The "other_approval" task should be in state "finished".'',
''finished'',
v_state
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id
and state = ''enabled'';
PERFORM utassert__eq(
''We should have exactly one task enabled'',
1,
v_count
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id
and transition_key = ''buy''
and state = ''enabled'';
PERFORM utassert__eq(
''We should have the "buy" task enabled'',
1,
v_count
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id;
PERFORM utassert__eq(
''There should be exactly seven tasks for this case, one canceled, six finished, and one enabled.'',
7,
v_count
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id
and state = ''finished'';
PERFORM utassert__eq(
''There should be exactly five finished tasks'',
5,
v_count
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id
and state = ''canceled'';
PERFORM utassert__eq(
''There should be exactly one canceled task'',
1,
v_count
);
raise NOTICE ''. finish task "buy"'';
/* Get that task_id for the ''buy'' task */
select task_id into v_task_id
from wf_tasks
where case_id = v_case_id
and transition_key = ''buy''
and state = ''enabled'';
v_journal_id := workflow_case__begin_task_action(
v_task_id,
''finish'',
''0.0.0.0'',
v_user_id,
''regression-test: finished task "buy"''
);
PERFORM workflow_case__end_task_action(
v_journal_id,
''finish'',
v_task_id
);
select state into v_state
from wf_tasks
where task_id = v_task_id;
PERFORM utassert__eq(
''The "buy" task should be in state "finished".'',
''finished'',
v_state
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id;
PERFORM utassert__eq(
''There should be exactly seven tasks for this case, one canceled, six finished, and one enabled.'',
7,
v_count
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id
and state = ''finished'';
PERFORM utassert__eq(
''There should be exactly six finished tasks'',
6,
v_count
);
select count(*) into v_count
from wf_tasks
where case_id = v_case_id
and state = ''canceled'';
PERFORM utassert__eq(
''There should be exactly one canceled task'',
1,
v_count
);
select state into v_state
from wf_cases
where case_id = v_case_id;
PERFORM utassert__eq(
''The case should be finished'',
''finished'',
v_state
);
--utresult.show;
return null;
end;' language 'plpgsql';
SELECT setup ();
SELECT run ();
drop function setup();
drop function run();
drop function teardown();
drop function utassert__eq(varchar,integer,integer);
drop function utassert__eq(varchar,text,text);
acs-workflow-master/sql/postgresql/upgrade/ 0000775 0000000 0000000 00000000000 14575002472 0021424 5 ustar 00root root 0000000 0000000 acs-workflow-master/sql/postgresql/upgrade/upgrade-4.0-4.0.1.sql 0000664 0000000 0000000 00000027137 14575002472 0024543 0 ustar 00root root 0000000 0000000 -- Recreating almost all foreign key constraints in order to add "on delete cascade"
-- wf_workflows
alter table wf_workflows drop constraint wf_workflows_workflow_key_fk;
alter table wf_workflows add (
constraint wf_workflows_workflow_key_fk
foreign key(workflow_key) references acs_object_types(object_type) on delete cascade
);
-- wf_places
alter table wf_places drop constraint wf_place_workflow_fk;
alter table wf_places add (
constraint wf_place_workflow_fk
foreign key(workflow_key) references wf_workflows(workflow_key) on delete cascade
);
-- wf_transitions
alter table wf_transitions drop constraint wf_transition_workflow_fk;
alter table wf_transitions add (
constraint wf_transition_workflow_fk
foreign key(workflow_key) references wf_workflows(workflow_key) on delete cascade
);
-- wf_arcs
alter table wf_arcs drop constraint wf_ts_arc_workflow_fk;
alter table wf_arcs add (
constraint wf_ts_arc_workflow_fk
foreign key(workflow_key) references wf_workflows(workflow_key) on delete cascade
);
alter table wf_arcs drop constraint wf_arc_transition_fk;
alter table wf_arcs add (
constraint wf_arc_transition_fk
foreign key(workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
alter table wf_arcs drop constraint wf_arc_place_fk;
alter table wf_arcs add (
constraint wf_arc_place_fk
foreign key(workflow_key, place_key) references wf_places(workflow_key, place_key) on delete cascade
);
create index wf_arcs_wf_key_trans_key_idx on wf_arcs(workflow_key, transition_key);
create index wf_arcs_wf_key_place_key_idx on wf_arcs(workflow_key, place_key);
-- wf_attribute_info
alter table wf_attribute_info add (
constraint wf_attribute_info_attribute_pk primary key(attribute_id)
);
alter table wf_attribute_info drop constraint wf_attribute_info_attribute_fk;
alter table wf_attribute_info add (
constraint wf_attribute_info_attribute_fk
foreign key(attribute_id) references acs_attributes(attribute_id) on delete cascade
);
-- wf_transition_attribute_map
alter table wf_transition_attribute_map drop constraint wf_trans_attr_map_workflow_fk;
alter table wf_transition_attribute_map add (
constraint wf_trans_attr_map_workflow_fk
foreign key(workflow_key) references wf_workflows(workflow_key) on delete cascade
);
alter table wf_transition_attribute_map drop constraint wf_trans_attr_map_trans_fk;
alter table wf_transition_attribute_map add (
constraint wf_trans_attr_map_trans_fk
foreign key(workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
-- wf_transition_assignment_map
alter table wf_transition_assignment_map drop constraint wf_trans_asgn_map_workflow_fk;
alter table wf_transition_assignment_map add (
constraint wf_trans_asgn_map_workflow_fk
foreign key(workflow_key) references wf_workflows(workflow_key) on delete cascade
);
alter table wf_transition_assignment_map drop constraint wf_trans_asgn_map_trans_fk;
alter table wf_transition_assignment_map add (
constraint wf_trans_asgn_map_trans_fk
foreign key(workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
alter table wf_transition_assignment_map drop constraint wf_tr_asgn_map_asgn_trans_fk;
alter table wf_transition_assignment_map add (
constraint wf_tr_asgn_map_asgn_trans_fk
foreign key(workflow_key, assign_transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
create index wf_trans_asgn_map_wf_trans_idx on wf_transition_assignment_map(workflow_key, transition_key);
create index wf_trans_asgn_map_wf_as_tr_idx on wf_transition_assignment_map(workflow_key, assign_transition_key);
-- wf_context_transition_info
alter table wf_context_transition_info drop constraint wf_context_trans_trans_fk;
alter table wf_context_transition_info add (
constraint wf_context_trans_trans_fk
foreign key(workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
create index wf_ctx_trans_wf_trans_idx on wf_context_transition_info(workflow_key, transition_key);
-- wf_context_assignments
alter table wf_context_assignments drop constraint wf_context_assign_context_fk;
alter table wf_context_assignments add (
constraint wf_context_assign_context_fk
foreign key(context_key) references wf_contexts(context_key) on delete cascade
);
alter table wf_context_assignments drop constraint wf_context_assign_workflow_fk;
alter table wf_context_assignments add (
constraint wf_context_assign_workflow_fk
foreign key(workflow_key) references wf_workflows(workflow_key) on delete cascade
);
alter table wf_context_assignments drop constraint wf_context_assign_party_fk;
alter table wf_context_assignments add (
constraint wf_context_assign_party_fk
foreign key(party_id) references parties(party_id) on delete cascade
);
alter table wf_context_assignments drop constraint wf_context_assign_trans_fk;
alter table wf_context_assignments add (
constraint wf_context_assign_trans_fk
foreign key(workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
create index wf_ctx_assg_workflow_trans_idx on wf_context_assignments(workflow_key, transition_key);
-- wf_cases
alter table wf_cases drop constraint wf_cases_acs_object_fk;
alter table wf_cases add (
constraint wf_cases_acs_object_fk
foreign key(case_id) references acs_objects(object_id) on delete cascade
);
alter table wf_cases drop constraint wf_cases_workflow_fk;
alter table wf_cases add (
constraint wf_cases_workflow_fk
foreign key(workflow_key) references wf_workflows(workflow_key) on delete cascade
);
alter table wf_cases drop constraint wf_cases_context_fk;
alter table wf_cases add (
constraint wf_cases_context_fk
foreign key(context_key) references wf_contexts(context_key) on delete cascade
);
alter table wf_cases drop constraint wf_cases_object_fk;
alter table wf_cases add (
constraint wf_cases_object_fk
foreign key(object_id) references acs_objects(object_id) on delete cascade
);
create index wf_cases_workflow_key_idx on wf_cases(workflow_key);
create index wf_cases_context_key_idx on wf_cases(context_key);
create index wf_cases_object_id_idx on wf_cases(object_id);
-- wf_case_assignments
alter table wf_case_assignments drop constraint wf_case_assign_fk;
alter table wf_case_assignments add (
constraint wf_case_assign_fk
foreign key(case_id) references wf_cases(case_id) on delete cascade
);
alter table wf_case_assignments drop constraint wf_case_assign_party_fk;
alter table wf_case_assignments add (
constraint wf_case_assign_party_fk
foreign key(party_id) references parties(party_id) on delete cascade
);
alter table wf_case_assignments drop constraint wf_case_assign_trans_fk;
alter table wf_case_assignments add (
constraint wf_case_assign_trans_fk
foreign key(workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
create index wf_case_assgn_party_idx on wf_case_assignments(party_id);
-- wf_case_deadlines
alter table wf_case_deadlines drop constraint wf_case_deadline_fk;
alter table wf_case_deadlines add (
constraint wf_case_deadline_fk
foreign key(case_id) references wf_cases(case_id) on delete cascade
);
alter table wf_case_deadlines drop constraint wf_case_deadline_trans_fk;
alter table wf_case_deadlines add (
constraint wf_case_deadline_trans_fk
foreign key(workflow_key, transition_key) references wf_transitions(workflow_key, transition_key) on delete cascade
);
-- wf_tasks
alter table wf_tasks drop constraint wf_task_case_fk;
alter table wf_tasks add (
constraint wf_task_case_fk
foreign key(case_id) references wf_cases(case_id) on delete cascade
);
alter table wf_tasks drop constraint wf_task_holding_user_fk;
alter table wf_tasks add (
constraint wf_task_holding_user_fk
foreign key(holding_user) references users(user_id) on delete cascade
);
create index wf_tasks_case_id_idx on wf_tasks(case_id);
create index wf_tasks_holding_user_idx on wf_tasks(holding_user);
-- wf_task_assignments
alter table wf_task_assignments drop constraint wf_task_assign_task_fk;
alter table wf_task_assignments add (
constraint wf_task_assign_task_fk
foreign key(task_id) references wf_tasks(task_id) on delete cascade
);
alter table wf_task_assignments drop constraint wf_task_party_fk;
alter table wf_task_assignments add (
constraint wf_task_party_fk
foreign key(party_id) references parties(party_id) on delete cascade
);
create index wf_task_asgn_party_id_idx on wf_task_assignments(party_id);
-- wf_tokens
alter table wf_tokens drop constraint wf_token_workflow_instance_fk;
alter table wf_tokens add (
constraint wf_token_workflow_instance_fk
foreign key(case_id) references wf_cases(case_id) on delete cascade
);
create index wf_tokens_case_id_idx on wf_tokens(case_id);
-- wf_attribute_value_audit
alter table wf_attribute_value_audit drop constraint wf_attr_val_audit_case_fk;
alter table wf_attribute_value_audit add (
constraint wf_attr_val_audit_case_fk
foreign key(case_id) references wf_cases(case_id) on delete cascade
);
alter table wf_attribute_value_audit drop constraint wf_attr_val_audit_attr_fk;
alter table wf_attribute_value_audit add (
constraint wf_attr_val_audit_attr_fk
foreign key(attribute_id) references acs_attributes(attribute_id) on delete cascade
);
create index wf_attr_val_aud_attr_id_idx on wf_attribute_value_audit(attribute_id);
-- Added a column to wf_tasks
alter table wf_tasks add (estimated_minutes integer);
-- We've added the column estimated_minutes to this view.
create or replace view wf_enabled_transitions as
select c.case_id,
t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.context_key,
t.enable_callback,
t.enable_custom_arg,
t.fire_callback,
t.fire_custom_arg,
t.assignment_callback,
t.assignment_custom_arg,
t.time_callback,
t.time_custom_arg,
t.deadline_callback,
t.deadline_custom_arg,
t.deadline_attribute_name,
t.hold_timeout_callback,
t.hold_timeout_custom_arg,
t.estimated_minutes
from wf_transition_info t,
wf_cases c
where t.workflow_key = c.workflow_key
and t.context_key = c.context_key
and c.state = 'active'
and not exists
(select tp.place_key
from wf_transition_places tp
where tp.transition_key = t.transition_key
and tp.workflow_key = t.workflow_key
and tp.direction = 'in'
and not exists
(select tk.token_id
from wf_tokens tk
where tk.place_key = tp.place_key
and tk.case_id = c.case_id
and tk.state = 'free'
)
);
-- We've added the column workflow_key to this view
create or replace view wf_user_tasks as
select distinct ta.task_id,
ta.case_id,
ta.workflow_key,
ta.transition_key,
tr.transition_name,
ta.enabled_date,
ta.started_date,
u.user_id,
ta.state,
ta.holding_user,
ta.hold_timeout,
ta.deadline,
ta.estimated_minutes
from wf_tasks ta,
wf_task_assignments tasgn,
wf_cases c,
wf_transition_info tr,
party_approved_member_map m,
users u
where ta.state in ( 'enabled','started')
and c.case_id = ta.case_id
and c.state = 'active'
and tr.transition_key = ta.transition_key
and tr.trigger_type = 'user'
and tr.context_key = c.context_key
and tasgn.task_id = ta.task_id
and m.party_id = tasgn.party_id
and u.user_id = m.member_id;
acs-workflow-master/sql/postgresql/upgrade/upgrade-4.0.1-4.1b.sql 0000664 0000000 0000000 00000012323 14575002472 0024675 0 ustar 00root root 0000000 0000000 /*
* Panels callbacks have changed.
*
* Instead of a Tcl callback (sick idea, we knew that all along),
* we now store a list of URLs of templates to include.
*/
/* Drop the old column */
alter table wf_context_transition_info drop column panels_callback_tcl;
/* Add the new table instead */
create table wf_context_task_panels (
context_key varchar2(100) not null
constraint wf_context_panels_context_fk
references wf_contexts(context_key)
on delete cascade,
workflow_key varchar2(100) not null
constraint wf_context_panels_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
transition_key varchar2(100) not null,
sort_key integer not null,
header varchar2(200) not null,
template_url varchar2(500) not null,
/* table constraints */
constraint wf_context_panels_trans_fk
foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key)
on delete cascade,
constraint wf_context_panels_pk
primary key (context_key, workflow_key, transition_key, sort_key)
);
create index wf_ctx_panl_workflow_trans_idx on wf_context_task_panels(workflow_key, transition_key);
comment on table wf_context_task_panels is '
Holds information about the panels to be displayed on the task page.
';
/*
* Added a Notification callback.
*
*/
alter table wf_context_transition_info add (
/*
* Notification callback
* Will be called when a notification is sent i.e., when a transition is enabled,
* or assignment changes.
* signature: (task_id in number,
* custom_arg in varchar2,
* party_to in integer,
* party_from in out integer,
* subject in out varchar2,
* body in out varchar2)
*/
notification_callback varchar2(100),
notification_custom_arg varchar2(4000)
);
/*
* Enhanced comment on wf_cases.object_id
*
*/
comment on column wf_cases.object_id is '
A case is itself an acs_object, but moreover, a case will always be about some
other acs_object. E.g. for ticket-tracker, the case_id will refer to an instance of
the ticket-tracker-workflow, while the object_id will refer to the ticket itself.
It is possible to have multiple cases around the same object.
';
/*
* Added unassigned callback
*/
alter table wf_context_transition_info add (
/*
* Unassigned callback
* Will be called whenever a task becomes unassigned
* Signature: (case_id in number, transition_key in varchar2, custom_arg in varchar2)
*/
unassigned_callback varchar2(100),
unassigned_custom_arg varchar2(4000)
);
/*
* Added access privilege
*/
alter table wf_context_transition_info add (
/* name of the privilege we should check before allowing access
* to task information.
*/
access_privilege varchar2(100)
);
/* panels_callback_tcl, notification_callback and unassigned_callback
* affect this view.
*/
create or replace view wf_transition_info as
select t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.context_key,
ct.estimated_minutes,
ct.enable_callback,
ct.enable_custom_arg,
ct.fire_callback,
ct.fire_custom_arg,
ct.assignment_callback,
ct.assignment_custom_arg,
ct.time_callback,
ct.time_custom_arg,
ct.deadline_callback,
ct.deadline_custom_arg,
ct.deadline_attribute_name,
ct.hold_timeout_callback,
ct.hold_timeout_custom_arg,
ct.notification_callback,
ct.notification_custom_arg,
ct.unassigned_callback,
ct.unassigned_custom_arg,
ct.access_privilege
from wf_transition_contexts t, wf_context_transition_info ct
where ct.workflow_key (+) = t.workflow_key
and ct.transition_key (+) = t.transition_key
and ct.context_key (+) = t.context_key;
/* Notifications and unassigned affect this */
create or replace view wf_enabled_transitions as
select c.case_id,
t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.context_key,
t.enable_callback,
t.enable_custom_arg,
t.fire_callback,
t.fire_custom_arg,
t.assignment_callback,
t.assignment_custom_arg,
t.time_callback,
t.time_custom_arg,
t.deadline_callback,
t.deadline_custom_arg,
t.deadline_attribute_name,
t.hold_timeout_callback,
t.hold_timeout_custom_arg,
t.notification_callback,
t.notification_custom_arg,
t.unassigned_callback,
t.unassigned_custom_arg,
t.estimated_minutes,
t.access_privilege
from wf_transition_info t,
wf_cases c
where t.workflow_key = c.workflow_key
and t.context_key = c.context_key
and c.state = 'active'
and not exists
(select tp.place_key
from wf_transition_places tp
where tp.transition_key = t.transition_key
and tp.workflow_key = t.workflow_key
and tp.direction = 'in'
and not exists
(select tk.token_id
from wf_tokens tk
where tk.place_key = tp.place_key
and tk.case_id = c.case_id
and tk.state = 'free'
)
);
acs-workflow-master/sql/postgresql/upgrade/upgrade-4.1.1-4.3.sql 0000664 0000000 0000000 00000053455 14575002472 0024551 0 ustar 00root root 0000000 0000000 /*
* We've added support for roles, which is an intermediate step between
* transitions and assignments. A role is a relationship to a process, e.g.,
* an editor, publisher, submitter, fixer, doctor, manager, etc.
* A task is performed by a role, but one role may have many tasks to perform.
* The idea is that when you reassign a role, it affects all the tasks that role
* has been assigned to.
*
* For the upgrade, we simply create one role per transtiion, and change
* all the other tables correspondingly. This will execute exactly equivalent
* to the way it would have without the roles refactoring.
*
* We've also added other minor things, such as task instructions and gotten rid
* of wf_attribute_info.
*/
/*
* Table wf_roles:
* Added.
*/
create table wf_roles (
role_key varchar(100),
workflow_key varchar(100)
constraint wf_roles_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
role_name varchar(100)
constraint wf_role_role_name_nn
not null,
-- so we can display roles in some logical order --
sort_order integer
constraint wf_roles_order_ck
check (sort_order > 0),
-- table constraints --
constraint wf_role_pk
primary key (workflow_key, role_key),
constraint wf_roles_wf_key_role_name_un
unique (workflow_key, role_name)
);
comment on table wf_roles is '
A process has certain roles associated with it, such as "submitter",
"reviewer", "editor", "claimant", etc. For each transition, then, you
specify what role is to perform that task. Thus, two or more tasks can be
performed by one and the same role, so that when the role is reassigned,
it reflects assignments of both tasks. Users and parties are then assigned
to roles instead of directly to tasks.
';
/*
* Now populate the roles table:
* We just create a role per transition, then hook them up
*/
insert into wf_roles
(workflow_key,
role_key,
role_name,
sort_order)
select workflow_key, transition_key, transition_name, sort_order
from wf_transitions;
/*
* Table wf_transitions:
* Added column role_key.
* Added foreign key constraint wf_transition_role_fk.
*/
alter table wf_transitions add role_key varchar(100);
alter table wf_transitions add constraint wf_transition_role_fk
foreign key (workflow_key,role_key) references wf_roles(workflow_key,role_key);
/* We don't do on delete cascade here, because that would mean that
* when a role is deleted, the transitions associated with that role would be deleted, too */
/* Now populate the new column corresponding to the roles we just created:
* Since there's a one-to-one role per transition, and the have the same keys,
* we just set role_key = transition_key
*/
update wf_transitions
set role_key = transition_key;
/*
* Table wf_transition_role_assign_map:
* Added.
* This replaces wf_transtiion_assign_map, since transitions now assign
* roles instead of other transitions.
*/
create table wf_transition_role_assign_map (
workflow_key varchar(100)
constraint wf_role_asgn_map_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
transition_key varchar(100),
assign_role_key varchar(100),
-- table constraints --
constraint wf_role_asgn_map_pk
primary key (workflow_key, transition_key, assign_role_key),
constraint wf_role_asgn_map_trans_fk
foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key)
on delete cascade,
constraint wf_tr_role_asgn_map_asgn_fk
foreign key (workflow_key, assign_role_key) references wf_roles(workflow_key, role_key)
on delete cascade
);
create index wf_role_asgn_map_wf_trans_idx on wf_transition_role_assign_map(workflow_key, transition_key);
create index wf_role_asgn_map_wf_as_tr_idx on wf_transition_role_assign_map(workflow_key, assign_role_key);
comment on table wf_transition_role_assign_map is '
When part of the output of one task is to assign users to a role,
specify that this is the case by inserting a row here.
';
comment on column wf_transition_role_assign_map.transition_key is '
transition_key is the assigning transition.
';
comment on column wf_transition_role_assign_map.assign_role_key is '
assign_role_key is the role being assigned a user to.
';
/* Populate new wf_transition_role_assign_map with the rows from
* wf_transition_assignment_map. Since role_key map one-to-one with transition_keys
* in this upgrade, that's pretty straight-forward.
*/
insert into wf_transition_role_assign_map
(workflow_key,
transition_key,
assign_role_key)
select workflow_key,
transition_key,
assign_transition_key
from wf_transition_assignment_map;
/*
* Table wf_transition_assignment_map:
* Dropped.
* This table is no longer releavnt, since transitions don't assign other
* transitions, they assign roles.
*/
drop table wf_transition_assignment_map;
/*
* Table wf_attribute_info:
* Dropped.
* This table was a hang-over from earlier versions and is no longer necessary.
*/
drop table wf_attribute_info;
/*
* Table wf_context_role_info:
* Added.
*/
create table wf_context_role_info (
context_key varchar(100)
constraint wf_context_role_context_fk
references wf_contexts(context_key)
on delete cascade,
workflow_key varchar(100)
constraint wf_context_role_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
role_key varchar(100),
/*
* Callback to programatically assign a role.
* Must call wordflow_case.*_role_assignment to make the assignments.
* Will be called when a transition for that role becomes enabled
* signature: (role_key in varchar2, custom_arg in varchar2)
*/
assignment_callback varchar(100),
assignment_custom_arg text,
-- table constraints --
constraint wf_context_role_role_fk
foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key)
on delete cascade,
constraint wf_context_role_info_pk
primary key (context_key, workflow_key, role_key)
);
comment on table wf_context_role_info is '
This table holds context-dependent info for roles, currently only the assignment callback
';
/* Populate by a straight copy from wf_context_transition_info */
insert into wf_context_role_info
(context_key,
workflow_key,
role_key,
assignment_callback,
assignment_custom_arg)
select context_key,
workflow_key,
transition_key,
assignment_callback,
assignment_custom_arg
from wf_context_transition_info
where assignment_callback is not null
or assignment_custom_arg is not null;
/*
* Table wf_context_transition_info:
*/
create table temp as select
context_key,
workflow_key,
transition_key,
estimated_minutes,
enable_callback,
enable_custom_arg,
fire_callback,
fire_custom_arg,
time_callback,
time_custom_arg,
deadline_callback,
deadline_custom_arg,
deadline_attribute_name,
hold_timeout_callback,
hold_timeout_custom_arg,
notification_callback,
notification_custom_arg,
unassigned_callback,
unassigned_custom_arg,
access_privilege
from wf_context_transition_info;
drop table wf_context_transition_info;
create table wf_context_transition_info (
context_key varchar(100)
constraint wf_context_trans_context_fk
references wf_contexts,
workflow_key varchar(100)
constraint wf_context_trans_workflow_fk
references wf_workflows,
transition_key varchar(100),
/* information for the transition in the context */
/* The integer of minutes this task is estimated to take */
estimated_minutes integer,
/* Instructions for how to complete the task. Will be displayed on the task page. */
instructions text,
/*
* Will be called when the transition is enabled/fired.
* signature: (case_id in integer, transition_key in varchar, custom_arg in varchar2)
*/
enable_callback varchar(100),
enable_custom_arg text,
fire_callback varchar(100),
fire_custom_arg text,
/*
* Must return the date that the timed transition should fire
* Will be called when the transition is enabled
* signature: (case_id in integer, transition_key in varchar, custom_arg in varchar2) return date
*/
time_callback varchar(100),
time_custom_arg text,
/*
* Returns the deadline for this task.
* Will be called when the transition becomes enabled
* Signature: (case_id in integer, transition_key in varchar, custom_arg in varchar2) return date
*/
deadline_callback varchar(100),
deadline_custom_arg text,
/* The name of an attribute that holds the deadline */
deadline_attribute_name varchar(100),
/*
* Must return the date that the user's hold on the task times out.
* called when the user starts the task.
* signature: (case_id in integer, transition_key in varchar, custom_arg in varchar2) return date
*/
hold_timeout_callback varchar(100),
hold_timeout_custom_arg text,
/*
* Notification callback
* Will be called when a notification is sent i.e., when a transition is enabled,
* or assignment changes.
* signature: (task_id in integer,
* custom_arg in varchar,
* party_to in integer,
* party_from in out integer,
* subject in out varchar,
* body in out varchar)
*/
notification_callback varchar(100),
notification_custom_arg text,
/*
* Callback to handle unassigned tasks.
* Will be called when an enabled task becomes unassigned.
* Signature: (task_id in number, custom_arg in varchar2)
*/
unassigned_callback varchar(100),
unassigned_custom_arg text,
-- table constraints --
constraint wf_context_trans_trans_fk
foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key)
on delete cascade,
constraint wf_context_transition_pk
primary key (context_key, workflow_key, transition_key)
);
create index wf_ctx_trans_wf_trans_idx on wf_context_transition_info(workflow_key, transition_key);
comment on table wf_context_transition_info is '
This table holds information that pertains to a transition in a specific context.
It will specifically hold
';
insert into wf_context_transition_info select * from temp;
drop table temp;
/*
* Table wf_context_workflow_info:
* Added.
*/
create table wf_context_workflow_info (
context_key varchar(100)
constraint wf_context_wf_context_fk
references wf_contexts
on delete cascade,
workflow_key varchar(100)
constraint wf_context_wf_workflow_fk
references wf_workflows
on delete cascade,
/* The principal is the user/party that sends out email assignment notifications
* And receives email when a task becomes unassigned (for more than x minutes?)
*/
principal_party integer
constraint wf_context_wf_principal_fk
references parties
on delete set null,
-- table constraints --
constraint wf_context_workflow_pk
primary key (context_key, workflow_key)
);
/* Insert someone for all existing processes. Hopefully this will be the administrator user. */
insert into wf_context_workflow_info
(context_key,
workflow_key,
principal_party)
select 'default', workflow_key, (select min(party_id) from parties)
from wf_workflows;
/*
* Table wf_context_task_panels:
* Added columns overrides_action_p and only_display_when_started_p
* Renamed column sort_key to sort_order for consistency
*/
create table temp as select
context_key,
workflow_key,
transition_key,
sort_key as sort_order,
header,
template_url
from wf_context_task_panels;
drop table wf_context_task_panels;
create table wf_context_task_panels (
context_key varchar(100) not null
constraint wf_context_panels_context_fk
references wf_contexts(context_key)
on delete cascade,
workflow_key varchar(100) not null
constraint wf_context_panels_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
transition_key varchar(100) not null,
sort_order integer not null,
header varchar(200) not null,
template_url varchar(500) not null,
/* Display this panel in place of the action panel */
overrides_action_p char(1) default 'f'
constraint wf_context_panels_ovrd_p_ck
check (overrides_action_p in ('t','f')),
/* Display this panel only when the task has been started (and not finished) */
only_display_when_started_p char(1) default 'f'
constraint wf_context_panels_display_p_ck
check (only_display_when_started_p in ('t','f')),
-- table constraints --
constraint wf_context_panels_trans_fk
foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key)
on delete cascade,
constraint wf_context_panels_pk
primary key (context_key, workflow_key, transition_key, sort_order)
);
create index wf_ctx_panl_workflow_trans_idx on wf_context_task_panels(workflow_key, transition_key);
comment on table wf_context_task_panels is '
Holds information about the panels to be displayed on the task page.
';
insert into wf_context_task_panels select * from temp;
drop table temp;
/*
* Table wf_context_assignments
* Replaced transition_key with role_key
*/
create table temp as select
context_key,
workflow_key,
transition_key as role_key,
party_id
from wf_context_assignments;
drop table wf_context_assignments;
create table wf_context_assignments (
context_key varchar(100)
constraint wf_context_assign_context_fk
references wf_contexts(context_key)
on delete cascade,
workflow_key varchar(100)
constraint wf_context_assign_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
role_key varchar(100),
party_id integer
constraint wf_context_assign_party_fk
references parties(party_id)
on delete cascade,
-- table constraints --
constraint wf_context_assign_pk
primary key (context_key, workflow_key, role_key, party_id),
constraint wf_context_assign_role_fk
foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key)
on delete cascade
);
create index wf_ctx_assg_workflow_trans_idx on wf_context_assignments(workflow_key, role_key);
comment on table wf_context_assignments is '
Static (default) per-context assignments of roles to parties.
';
insert into wf_context_assignments select * from temp;
drop table temp;
/*
* Table wf_case_assignments:
* Changed transition_key to role_key
*/
create table temp as select
case_id,
workflow_key,
transition as role_key,
party_id
from wf_case_assignments;
drop table wf_case_assignments;
create table wf_case_assignments (
case_id integer
constraint wf_case_assign_fk
references wf_cases(case_id)
on delete cascade,
workflow_key varchar(100),
role_key varchar(100),
party_id integer
constraint wf_case_assign_party_fk
references parties(party_id)
on delete cascade,
-- table constraints --
constraint wf_case_assign_pk
primary key (case_id, role_key, party_id),
constraint wf_case_assign_role_fk
foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key)
on delete cascade
);
create index wf_case_assgn_party_idx on wf_case_assignments(party_id);
comment on table wf_case_assignments is '
Manual per-case assignments of roles to parties.
';
insert into wf_case_assignments select * from temp;
drop table temp;
/*
* View wf_transition_contexts:
* Added column role_key.
*/
drop view wf_transition_contexts;
create view wf_transition_contexts as
select t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.role_key,
c.context_key,
c.context_name
from wf_transitions t, wf_contexts c;
/*
* View wf_transition_info:
* Added columns role_key and instructions.
* Removed columns assignment_callback/custom_arg.
*/
drop view wf_transition_info;
create view wf_transition_info as
select t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.context_key,
t.role_key,
ct.estimated_minutes,
ct.instructions,
ct.enable_callback,
ct.enable_custom_arg,
ct.fire_callback,
ct.fire_custom_arg,
ct.time_callback,
ct.time_custom_arg,
ct.deadline_callback,
ct.deadline_custom_arg,
ct.deadline_attribute_name,
ct.hold_timeout_callback,
ct.hold_timeout_custom_arg,
ct.notification_callback,
ct.notification_custom_arg,
ct.unassigned_callback,
ct.unassigned_custom_arg
from wf_transition_contexts t LEFT OUTER JOIN wf_context_transition_info ct ON (
ct.workflow_key = t.workflow_key
and ct.transition_key = t.transition_key
and ct.context_key = t.context_key);
/*
* View wf_role_info:
* Added.
*/
drop view wf_role_info;
create view wf_role_info as
select r.role_key,
r.role_name,
r.workflow_key,
c.context_key,
cr.assignment_callback,
cr.assignment_custom_arg
from wf_contexts c, wf_roles r LEFT OUTER JOIN wf_context_role_info cr ON (
cr.workflow_key = r.workflow_key
and cr.role_key = r.role_key)
where cr.context_key = c.context_key;
/*
* View wf_enabled_transitions:
* Added columns role_key and instructions.
* Removed columns assignment_callback/custom_arg.
*/
drop view wf_enabled_transitions;
create view wf_enabled_transitions as
select c.case_id,
t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.context_key,
t.role_key,
t.enable_callback,
t.enable_custom_arg,
t.fire_callback,
t.fire_custom_arg,
t.time_callback,
t.time_custom_arg,
t.deadline_callback,
t.deadline_custom_arg,
t.deadline_attribute_name,
t.hold_timeout_callback,
t.hold_timeout_custom_arg,
t.notification_callback,
t.notification_custom_arg,
t.estimated_minutes,
t.instructions,
t.unassigned_callback,
t.unassigned_custom_arg
from wf_transition_info t,
wf_cases c
where t.workflow_key = c.workflow_key
and t.context_key = c.context_key
and c.state = 'active'
and not exists
(select tp.place_key
from wf_transition_places tp
where tp.transition_key = t.transition_key
and tp.workflow_key = t.workflow_key
and tp.direction = 'in'
and not exists
(select tk.token_id
from wf_tokens tk
where tk.place_key = tp.place_key
and tk.case_id = c.case_id
and tk.state = 'free'
)
);
/*
* View wf_user_tasks:
* Added column instructions
* Added "and tr.workflow_key = ta.workflow_key" to where clause
* (looks like a bug)
*/
drop view wf_user_tasks;
create view wf_user_tasks as
select distinct ta.task_id,
ta.case_id,
ta.workflow_key,
ta.transition_key,
tr.transition_name,
tr.instructions,
ta.enabled_date,
ta.started_date,
u.user_id,
ta.state,
ta.holding_user,
ta.hold_timeout,
ta.deadline,
ta.estimated_minutes
from wf_tasks ta,
wf_task_assignments tasgn,
wf_cases c,
wf_transition_info tr,
party_approved_member_map m,
users u
where ta.state in ( 'enabled','started')
and c.case_id = ta.case_id
and c.state = 'active'
and tr.transition_key = ta.transition_key
and tr.workflow_key = ta.workflow_key
and tr.trigger_type = 'user'
and tr.context_key = c.context_key
and tasgn.task_id = ta.task_id
and m.party_id = tasgn.party_id
and u.user_id = m.member_id;
drop function __workflow__simple_p (varchar,integer);
drop table guard_list;
drop table target_place_list;
drop table previous_place_list;
drop sequence workflow_session_id;
drop function sweep_hold_timeout ();
drop function sweep_timed_transitions ();
select drop_package('workflow');
select drop_package('workflow_case');
\i workflow-package.sql
\i workflow-case-package-head.sql
\i workflow-case-package-body.sql
acs-workflow-master/sql/postgresql/upgrade/upgrade-4.5.0-4.5.1.sql 0000664 0000000 0000000 00000011601 14575002472 0024700 0 ustar 00root root 0000000 0000000 -- upgrade-4.5.0-4.5.1.sql
-- Add a new column to determine that both panels should be overwritten
create or replace function inline_0 ()
returns integer as '
declare
v_count integer;
begin
select count(*)
into v_count
from user_tab_columns
where lower(table_name) = ''wf_context_task_panels''
and lower(column_name) = ''overrides_both_panels_p'';
if v_count = 1 then
return 0;
end if;
alter table wf_context_task_panels
add overrides_both_panels_p char(1)
constraint wf_context_panels_ovrd_both_ck
CHECK (overrides_both_panels_p = ''t'' OR overrides_both_panels_p = ''f'');
alter table wf_context_task_panels
alter column overrides_both_panels_p set default ''f'';
return 0;
end;' language 'plpgsql';
select inline_0 ();
drop function inline_0 ();
create or replace function workflow_case__add_task_assignment (integer,integer,boolean)
returns integer as '
declare
add_task_assignment__task_id alias for $1;
add_task_assignment__party_id alias for $2;
add_task_assignment__permanent_p alias for $3;
v_count integer;
v_workflow_key wf_workflows.workflow_key%TYPE;
v_context_key wf_contexts.context_key%TYPE;
v_case_id wf_cases.case_id%TYPE;
v_role_key wf_roles.role_key%TYPE;
v_transition_key wf_transitions.transition_key%TYPE;
v_notification_callback wf_context_transition_info.notification_callback%TYPE;
v_notification_custom_arg wf_context_transition_info.notification_custom_arg%TYPE;
callback_rec record;
v_assigned_user record;
begin
-- get some needed information
select ta.case_id, ta.workflow_key, ta.transition_key, tr.role_key, c.context_key
into v_case_id, v_workflow_key, v_transition_key, v_role_key, v_context_key
from wf_tasks ta, wf_transitions tr, wf_cases c
where ta.task_id = add_task_assignment__task_id
and tr.workflow_key = ta.workflow_key
and tr.transition_key = ta.transition_key
and c.case_id = ta.case_id;
-- make the same assignment as a manual assignment
IF add_task_assignment__permanent_p = ''t'' and v_role_key is not null THEN
/* We do this up-front, because
* even though the user already had a task assignment,
* he might not have a case assignment.
*/
perform workflow_case__add_manual_assignment (
v_case_id,
v_role_key,
add_task_assignment__party_id
);
end if;
-- check that we do not hit the unique constraint
select count(*) into v_count
from wf_task_assignments
where task_id = add_task_assignment__task_id
and party_id = add_task_assignment__party_id;
if v_count > 0 then
return null;
end if;
-- get callback information
select notification_callback,
notification_custom_arg into callback_rec
from wf_context_transition_info
where context_key = v_context_key
and workflow_key = v_workflow_key
and transition_key = v_transition_key;
if FOUND then
v_notification_callback := callback_rec.notification_callback;
v_notification_custom_arg := callback_rec.notification_custom_arg;
else
v_notification_callback := null;
v_notification_custom_arg := null;
end if;
-- notify any new assignees
for v_assigned_user in
select distinct u.user_id
from users u
where u.user_id not in (
select distinct u2.user_id
from wf_task_assignments tasgn2,
party_approved_member_map m2,
users u2
where tasgn2.task_id = add_task_assignment__task_id
and m2.party_id = tasgn2.party_id
and u2.user_id = m2.member_id)
and exists (
select 1
from party_approved_member_map m
where m.member_id = u.user_id
and m.party_id = add_task_assignment__party_id
)
LOOP
PERFORM workflow_case__notify_assignee (
add_task_assignment__task_id,
v_assigned_user.user_id,
v_notification_callback,
v_notification_custom_arg
);
end loop;
-- do the insert
insert into wf_task_assignments (
task_id,
party_id
) values (
add_task_assignment__task_id,
add_task_assignment__party_id
);
return 0;
end;' language 'plpgsql';
acs-workflow-master/sql/postgresql/upgrade/upgrade-4.5.1-4.5.2.sql 0000664 0000000 0000000 00000000401 14575002472 0024676 0 ustar 00root root 0000000 0000000 -- upgrade-4.5.1-4.5.2.sql
-- Add a new "object_type" field per workflow in order
-- to define the type of object that this WF is about
alter table wf_workflows
add object_type varchar(100)
constraint wf_workflows_otype_fk
references acs_object_types;
acs-workflow-master/sql/postgresql/upgrade/upgrade-4.5.2-4.5.3.sql 0000664 0000000 0000000 00000002322 14575002472 0024704 0 ustar 00root root 0000000 0000000 -- upgrade-4.5.2-4.5.3.sql
-- Detecting the case of an empty return string,
-- representing a NULL value in TCL(?)
--
create or replace function wf_callback__guard_attribute_true (integer,varchar,varchar,varchar,varchar,varchar)
returns boolean as '
declare
guard_attribute_true__case_id alias for $1;
guard_attribute_true__workflow_key alias for $2;
guard_attribute_true__transition_key alias for $3;
guard_attribute_true__place_key alias for $4;
guard_attribute_true__direction alias for $5;
guard_attribute_true__custom_arg alias for $6;
v_value varchar;
begin
v_value := workflow_case__get_attribute_value(
guard_attribute_true__case_id,
guard_attribute_true__custom_arg
);
IF substring(v_value from 1 for 1) = ''t'' THEN return true; END IF;
IF substring(v_value from 1 for 1) = ''f'' THEN return false; END IF;
IF '''' = v_value THEN return null; END IF;
RAISE WARNING ''workflow_case__get_attribute_value(%,%) returned non-boolean value %'',
guard_attribute_true__case_id, guard_attribute_true__custom_arg, v_value;
return null;
end;' language 'plpgsql';
acs-workflow-master/sql/postgresql/upgrade/upgrade-4.5.3-4.5.4.sql 0000664 0000000 0000000 00000005362 14575002472 0024715 0 ustar 00root root 0000000 0000000 -- upgrade-4.5.3-4.5.4.sql
-- Fix: Failed update 11/2013 - coming from V3.2
-- we can't assume that im_lang_add_message already exists
create or replace function im_lang_add_message(text, text, text, text)
returns integer as $body$
DECLARE
p_locale alias for $1;
p_package_key alias for $2;
p_message_key alias for $3;
p_message alias for $4;
v_count integer;
BEGIN
-- Do not insert strings for packages that do not exist
--
select count(*) into v_count from apm_packages
where package_key = p_package_key;
IF 0 = v_count THEN return 0; END IF;
-- Make sure there is an entry in lang_message_keys
--
select count(*) into v_count from lang_message_keys
where package_key = p_package_key and message_key = p_message_key;
IF 0 = v_count THEN
insert into lang_message_keys (
message_key, package_key
) values (
p_message_key, p_package_key
);
END IF;
-- Create the translation entry
--
select count(*) into v_count from lang_messages
where locale = p_locale and package_key = p_package_key and message_key = p_message_key;
IF 0 = v_count THEN
insert into lang_messages (
message_key, package_key, locale, message, sync_time, upgrade_status
) values (
p_message_key, p_package_key, p_locale, p_message, now(), 'added'
);
END IF;
return 1;
END;$body$ language 'plpgsql';
-- Localization
SELECT im_lang_add_message('en_US','acs-workflow','Task_Has_Not_Been_Started_Yet','This task has not been started yet.');
SELECT im_lang_add_message('de_DE','acs-workflow','Task_Has_Not_Been_Started_Yet','Workflow Aufgabe noch nicht gestarted');
SELECT im_lang_add_message('en_US','acs-workflow','You_Are_The_Only_Person','You are the only person assigned to this task.');
SELECT im_lang_add_message('de_DE','acs-workflow','You_Are_The_Only_Person','Sie sind alleiniger Aufgabenträger ');
SELECT im_lang_add_message('en_US','acs-workflow','Other_Assignees','Other assignees:');
SELECT im_lang_add_message('de_DE','acs-workflow','Other_Assignees','Weitere Aufgabentr@auml;ger:');
SELECT im_lang_add_message('en_US','acs-workflow','Assign_Yourself','assign yourself');
SELECT im_lang_add_message('de_DE','acs-workflow','Assign_Yourself','Aufgabe selbst ausführen');
SELECT im_lang_add_message('en_US','acs-workflow','Reassign','reassign');
SELECT im_lang_add_message('de_DE','acs-workflow','Reassign','Aufgabe anderer Person zuordnen');
acs-workflow-master/sql/postgresql/upgrade/upgrade-4.5.4-4.5.6.sql 0000664 0000000 0000000 00000023061 14575002472 0024714 0 ustar 00root root 0000000 0000000 -- upgrade-4.5.4-4.5.6.sql
-- Lookup localized message for workflow notification
create or replace function workflow_case__notify_l10n_lookup (varchar,varchar,varchar,varchar,varchar,integer)
returns varchar as $$
declare
p_message_prefix alias for $1;
p_notification_type alias for $2;
p_workflow_key alias for $3;
p_transition_key alias for $4;
p_locale alias for $5;
p_include_l10n_link alias for $6;
v_key varchar;
v_message varchar;
v_system_url varchar;
v_url varchar;
begin
RAISE NOTICE 'workflow_case__notify_l10n_lookup: prefx=%, notif_type=%, wf_key=%, trans_key=%, locale=%',
p_message_prefix, p_notification_type, p_workflow_key, p_transition_key, p_locale;
select apm__get_value((select package_id from apm_packages where package_key = 'acs-kernel'), 'SystemURL') into v_system_url;
-- ------------------------------------------------------------
-- Try with specific translation first
v_key := p_message_prefix || '_' || p_workflow_key || '_' || p_transition_key || '_' || p_notification_type;
v_message := acs_lang_lookup_message(p_locale, 'acs-workflow', v_key);
-- Fallback to more generic translation
IF substring(v_message from 1 for 7) = 'MISSING' THEN
v_key := p_message_prefix || '_' || p_workflow_key || '_' || p_transition_key;
v_message := acs_lang_lookup_message(p_locale, 'acs-workflow', v_key);
END IF;
-- Fallback to more generic translation
IF substring(v_message from 1 for 7) = 'MISSING' THEN
v_key := p_message_prefix || '_' || p_transition_key;
v_message := acs_lang_lookup_message(p_locale, 'acs-workflow', v_key);
END IF;
-- Fallback to more generic translation
IF substring(v_message from 1 for 7) = 'MISSING' THEN
v_key := p_message_prefix || '_' || p_transition_key;
v_message := acs_lang_lookup_message(p_locale, 'acs-workflow', v_key);
END IF;
-- Still no translation - create a message
IF p_include_l10n_link > 0 THEN
IF substring(v_message from 1 for 7) = 'MISSING' THEN
v_key := p_message_prefix || '_' || p_workflow_key || '_' || p_transition_key || '_' || p_notification_type;
v_url = v_system_url || '/acs-lang/admin/localized-message-new?package_key=acs-workflow&locale='||p_locale||'&message_key='||v_key;
v_message := E'Missing translation for message key\n\n'
|| E'Please visit the URL below with system administrator rights and create a translation\n'
|| v_url || E'\n\n'
|| E'Please also create a translation for the message subject by replacing the "Body" in the URL above with "Subject".'
|| E'\n\nSystem Administrator';
END IF;
END IF;
RAISE NOTICE 'workflow_case__notify_l10n_lookup: result=%', v_message;
return v_message;
end;$$ language 'plpgsql';
-- Compatibility proc - to maintain API
create or replace function workflow_case__notify_assignee (integer,integer,varchar,varchar)
returns integer as $$
declare
notify_assignee__task_id alias for $1;
notify_assignee__user_id alias for $2;
notify_assignee__callback alias for $3;
notify_assignee__custom_arg alias for $4;
begin
return workflow_case__notify_assignee($1,$2,$3,$4,null);
end;$$ language 'plpgsql';
-- Send out notification emails to assignees of workflow transitions
create or replace function workflow_case__notify_assignee (integer,integer,varchar,varchar,varchar)
returns integer as $$
declare
notify_assignee__task_id alias for $1;
notify_assignee__user_id alias for $2;
notify_assignee__callback alias for $3;
notify_assignee__custom_arg alias for $4;
notify_assignee__notification_type alias for $5;
v_deadline_pretty varchar;
v_object_name text;
v_workflow_key varchar;
v_transition_key wf_transitions.transition_key%TYPE;
v_transition_name wf_transitions.transition_name%TYPE;
v_party_from parties.party_id%TYPE;
v_party_to parties.party_id%TYPE;
v_subject text;
v_body text;
v_request_id integer;
v_workflow_url text;
v_acs_lang_package_id integer;
v_notifications_installed_p integer;
v_custom_arg varchar;
v_notification_type varchar;
v_notification_type_id integer;
v_workflow_package_id integer;
v_notification_n_seconds integer;
v_locale text;
v_str varchar;
v_user_first_names varchar;
v_user_last_name varchar;
v_sender_first_names varchar;
v_sender_last_name varchar;
begin
-- Default notification type
v_notification_type := notify_assignee__notification_type;
IF v_notification_type is null THEN
v_notification_type := 'wf_assignment_notif';
END IF;
-- Get information about the workflow context into variables
select to_char(ta.deadline,'Mon fmDDfm, YYYY HH24:MI:SS'),
acs_object__name(c.object_id), ta.workflow_key, tr.transition_key, tr.transition_name
into v_deadline_pretty, v_object_name, v_workflow_key, v_transition_key, v_transition_name
from wf_tasks ta, wf_transitions tr, wf_cases c
where ta.task_id = notify_assignee__task_id and
c.case_id = ta.case_id and
tr.workflow_key = c.workflow_key and
tr.transition_key = ta.transition_key;
select a.package_id, apm__get_value(p.package_id, 'SystemURL') || site_node__url(s.node_id)
into v_workflow_package_id, v_workflow_url
from site_nodes s, apm_packages a,
(select package_id
from apm_packages
where package_key = 'acs-kernel') p
where s.object_id = a.package_id and
a.package_key = 'acs-workflow';
v_workflow_url := v_workflow_url || 'task?task_id=' || notify_assignee__task_id;
select pe.first_names, pe.last_name
into v_user_first_names, v_user_last_name
from persons pe
where pe.person_id = notify_assignee__user_id;
RAISE NOTICE 'workflow_case__notify_assignee: task_id=%, user_id=%, obj=%, wf=%, trans=%',
notify_assignee__task_id, notify_assignee__user_id, v_object_name, v_workflow_key, v_transition_key;
select wfi.principal_party
into v_party_from
from wf_context_workflow_info wfi, wf_tasks ta, wf_cases c
where ta.task_id = notify_assignee__task_id and
c.case_id = ta.case_id and
wfi.workflow_key = c.workflow_key and
wfi.context_key = c.context_key;
if NOT FOUND then v_party_from := -1; end if;
-- Check whether the "notifications" package is installed and get
-- the notification interval of the user.
select count(*) into v_notifications_installed_p
from user_tab_columns
where lower(table_name) = 'notifications';
IF v_notifications_installed_p > 0 THEN
-- Notification Type is a kind of "channel" where to spread notifics
select type_id into v_notification_type_id
from notification_types
where short_name = v_notification_type;
-- Check if the user is "subscribed" to these notifications
select n_seconds into v_notification_n_seconds
from notification_requests r,
notification_intervals i
where r.interval_id = i.interval_id
and user_id = notify_assignee__user_id
and object_id = v_workflow_package_id
and type_id = v_notification_type_id;
-- Skip notification if there are no notifications defined
IF v_notification_n_seconds is null THEN return 0; END IF;
END IF;
-- Get the System Locale
select package_id into v_acs_lang_package_id
from apm_packages
where package_key = 'acs-lang';
v_locale := apm__get_value(v_acs_lang_package_id, 'SiteWideLocale');
-- make sure there are no null values - replaces(...,null) returns null...
IF v_deadline_pretty is NULL THEN v_deadline_pretty := 'undefined'; END IF;
IF v_workflow_url is NULL THEN v_workflow_url := 'undefined'; END IF;
-- ------------------------------------------------------------
-- Lookup message and substitute
v_subject := workflow_case__notify_l10n_lookup ('Notification_Subject', v_notification_type, v_workflow_key, v_transition_key, v_locale, 0);
v_subject := replace(v_subject, '%object_name%', v_object_name);
v_subject := replace(v_subject, '%transition_name%', v_transition_name);
v_subject := replace(v_subject, '%deadline%', v_deadline_pretty);
v_body := workflow_case__notify_l10n_lookup ('Notification_Body', v_notification_type, v_workflow_key, v_transition_key, v_locale, 1);
v_body := replace(v_body, '%deadline%', v_deadline_pretty);
v_body := replace(v_body, '%object_name%', v_object_name);
v_body := replace(v_body, '%transition_name%', v_transition_name);
v_body := replace(v_body, '%workflow_url%', v_workflow_url);
v_body := replace(v_body, '%first_names%', v_user_first_names);
v_body := replace(v_body, '%last_name%', v_user_last_name);
v_body := replace(v_body, '%user_first_names%', v_user_first_names);
v_body := replace(v_body, '%user_last_name%', v_user_last_name);
v_body := replace(v_body, '%sender_first_names%', v_sender_first_names);
v_body := replace(v_body, '%sender_last_name%', v_sender_last_name);
RAISE NOTICE 'workflow_case__notify_assignee: User=%, Subject=%, Body=%', v_user_first_names || ' ' || v_user_last_name, v_subject, v_body;
v_custom_arg := notify_assignee__custom_arg;
IF v_custom_arg is null THEN v_custom_arg := 'null'; END IF;
if notify_assignee__callback != '' and notify_assignee__callback is not null then
v_str := 'select ' || notify_assignee__callback || ' (' ||
notify_assignee__task_id || ',' ||
quote_literal(v_custom_arg) || ',' ||
notify_assignee__user_id || ',' ||
v_party_from || ',' ||
quote_literal(v_subject) || ',' ||
quote_literal(v_body) || ')';
execute v_str;
else
v_request_id := acs_mail_nt__post_request (
v_party_from, -- party_from
notify_assignee__user_id, -- party_to
'f', -- expand_group
v_subject, -- subject
v_body, -- message
0 -- max_retries
);
end if;
return 0;
end;$$ language 'plpgsql';
-- SELECT im_lang_add_message('en_US','acs-workflow','Task_Has_Not_Been_Started_Yet','This task has not been started yet.');
acs-workflow-master/sql/postgresql/upgrade/upgrade-4.5.6-4.5.7.sql 0000664 0000000 0000000 00000011331 14575002472 0024714 0 ustar 00root root 0000000 0000000 -- upgrade-4.5.6-4.5.7.sql
-- Deals with PostgreSQL 9.2 compatibility
-- procedure add_token
create or replace function workflow_case__add_token (integer,varchar,integer)
returns integer as $$
declare
add_token__case_id alias for $1;
add_token__place_key alias for $2;
add_token__journal_id alias for $3;
v_token_id integer;
v_workflow_key varchar;
begin
select nextval('t_wf_token_id_seq') into v_token_id from dual;
select workflow_key into v_workflow_key
from wf_cases c
where c.case_id = add_token__case_id;
insert into wf_tokens (
token_id, case_id, workflow_key, place_key, state, produced_journal_id
) values (
v_token_id, add_token__case_id, v_workflow_key, add_token__place_key,
'free', add_token__journal_id
);
return 0;
end;$$ language 'plpgsql';
-- procedure enable_transitions
create or replace function workflow_case__enable_transitions (integer)
returns integer as $$
declare
enable_transitions__case_id alias for $1;
v_task_id integer;
v_workflow_key varchar;
v_trigger_time timestamptz;
v_deadline_date timestamptz;
v_party_from integer;
v_subject varchar;
v_body text;
v_num_assigned integer;
trans_rec record;
begin
select workflow_key into v_workflow_key
from wf_cases
where case_id = enable_transitions__case_id;
/* we mark tasks overridden if they were once enabled, but are no longer so */
update wf_tasks
set state = 'overridden',
overridden_date = now()
where case_id = enable_transitions__case_id
and state = 'enabled'
and transition_key not in
(select transition_key
from wf_enabled_transitions
where case_id = enable_transitions__case_id);
/* insert a task for the transitions that are enabled but have no task row */
for trans_rec in select et.transition_key,
et.transition_name,
et.trigger_type,
et.enable_callback,
et.enable_custom_arg,
et.time_callback,
et.time_custom_arg,
et.deadline_callback,
et.deadline_custom_arg,
et.deadline_attribute_name,
et.notification_callback,
et.notification_custom_arg,
et.unassigned_callback,
et.unassigned_custom_arg,
et.estimated_minutes,
cr.assignment_callback,
cr.assignment_custom_arg
from wf_enabled_transitions et left outer join wf_context_role_info cr
on (et.workflow_key = cr.workflow_key and et.role_key = cr.role_key)
where et.case_id = enable_transitions__case_id
and not exists (select 1 from wf_tasks
where case_id = enable_transitions__case_id
and transition_key = et.transition_key
and state in ('enabled', 'started'))
LOOP
v_trigger_time := null;
v_deadline_date := null;
if trans_rec.trigger_type = 'user' then
v_deadline_date := workflow_case__get_task_deadline (
trans_rec.deadline_callback,
trans_rec.deadline_custom_arg,
trans_rec.deadline_attribute_name,
enable_transitions__case_id,
trans_rec.transition_key
);
end if;
v_trigger_time := workflow_case__execute_time_callback (
trans_rec.time_callback,
trans_rec.time_custom_arg,
enable_transitions__case_id,
trans_rec.transition_key);
/* we are ready to insert the row */
select nextval('t_wf_task_id_seq') into v_task_id from dual;
insert into wf_tasks (
task_id, case_id, workflow_key, transition_key,
deadline, trigger_time, estimated_minutes
) values (
v_task_id, enable_transitions__case_id, v_workflow_key,
trans_rec.transition_key,
v_deadline_date, v_trigger_time, trans_rec.estimated_minutes
);
PERFORM workflow_case__set_task_assignments (
v_task_id,
trans_rec.assignment_callback,
trans_rec.assignment_custom_arg
);
/* Execute the transition enabled callback */
PERFORM workflow_case__execute_transition_callback (
trans_rec.enable_callback,
trans_rec.enable_custom_arg,
enable_transitions__case_id,
trans_rec.transition_key
);
select count(*) into v_num_assigned
from wf_task_assignments
where task_id = v_task_id;
if v_num_assigned = 0 then
PERFORM workflow_case__execute_unassigned_callback (
trans_rec.unassigned_callback,
v_task_id,
trans_rec.unassigned_custom_arg
);
end if;
end loop;
return 0;
end;$$ language 'plpgsql';
acs-workflow-master/sql/postgresql/wf-callback-package-body.sql 0000664 0000000 0000000 00000002466 14575002472 0025220 0 ustar 00root root 0000000 0000000
-- create or replace package body wf_callback
-- function guard_attribute_true
create or replace function wf_callback__guard_attribute_true (integer,varchar,varchar,varchar,varchar,varchar)
returns boolean as $$
declare
guard_attribute_true__case_id alias for $1;
guard_attribute_true__workflow_key alias for $2;
guard_attribute_true__transition_key alias for $3;
guard_attribute_true__place_key alias for $4;
guard_attribute_true__direction alias for $5;
guard_attribute_true__custom_arg alias for $6;
v_value varchar;
begin
v_value := workflow_case__get_attribute_value(
guard_attribute_true__case_id,
guard_attribute_true__custom_arg
);
IF 't' = substring(v_value from 1 for 1) THEN return true; END IF;
IF 'f' = substring(v_value from 1 for 1) THEN return false; END IF;
return null;
end;$$ language 'plpgsql';
-- function time_sysdate_plus_x
create or replace function wf_callback__time_sysdate_plus_x (integer,varchar,text)
returns timestamptz as $$
declare
time_sysdate_plus_x__case_id alias for $1;
time_sysdate_plus_x__transition_key alias for $2;
time_sysdate_plus_x__custom_arg alias for $3;
begin
return now() + (time_sysdate_plus_x__custom_arg || ' days')::interval;
end;$$ language 'plpgsql';
acs-workflow-master/sql/postgresql/wf-callback-package-head.sql 0000664 0000000 0000000 00000000002 14575002472 0025144 0 ustar 00root root 0000000 0000000
acs-workflow-master/sql/postgresql/wf-callback-package.sql 0000664 0000000 0000000 00000000505 14575002472 0024255 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/wf-callback-package.sql
--
-- Creates the PL/SQL package that provides a small library of reusable
-- workflow callback functions/procedures.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
\i wf-callback-package-head.sql
\i wf-callback-package-body.sql
acs-workflow-master/sql/postgresql/wf-core-create.sql 0000664 0000000 0000000 00000067737 14575002472 0023345 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/wf-core-create.sql
--
-- Creates the data model and views for the workflow package.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
----------------------------------
-- KNOWLEDGE LEVEL OBJECTS
----------------------------------
/* Create the workflow superclass */
create function inline_0 ()
returns integer as $$
begin
PERFORM acs_object_type__create_type (
'workflow',
'Workflow',
'Workflow',
'acs_object',
'wf_cases',
'case_id',
null,
'f',
null,
null
);
return 0;
end;$$ language 'plpgsql';
select inline_0 ();
drop function inline_0 ();
-- show errors
create table wf_workflows (
workflow_key varchar(100)
constraint wf_workflows_pk
primary key
constraint wf_workflows_workflow_key_fk
references acs_object_types(object_type)
on delete cascade,
description text,
object_type varchar(100)
constraint wf_workflows_otype_fk
references acs_object_types
);
comment on table wf_workflows is '
Parent table for the workflow definition.
';
create table wf_places (
place_key varchar(100),
workflow_key varchar(100)
constraint wf_place_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
place_name varchar(100)
constraint wf_place_name_nn
not null,
-- so we can display places in some logical order --
sort_order integer
constraint wf_place_order_ck
check (sort_order > 0),
-- table constraints --
constraint wf_place_pk
primary key (workflow_key, place_key),
constraint wf_places_wf_key_place_name_un
unique (workflow_key, place_name)
);
comment on table wf_places is '
The circles of the petri net. These hold the tokens representing the overall
state of the workflow.
';
create table wf_roles (
role_key varchar(100),
workflow_key varchar(100)
constraint wf_roles_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
role_name varchar(100)
constraint wf_role_role_name_nn
not null,
-- so we can display roles in some logical order --
sort_order integer
constraint wf_roles_order_ck
check (sort_order > 0),
-- table constraints --
constraint wf_role_pk
primary key (workflow_key, role_key),
constraint wf_roles_wf_key_role_name_un
unique (workflow_key, role_name)
);
comment on table wf_roles is '
A process has certain roles associated with it, such as "submitter",
"reviewer", "editor", "claimant", etc. For each transition, then, you
specify what role is to perform that task. Thus, two or more tasks can be
performed by one and the same role, so that when the role is reassigned,
it reflects assignments of both tasks. Users and parties are then assigned
to roles instead of directly to tasks.
';
create table wf_transitions (
transition_key varchar(100),
transition_name varchar(100)
constraint wf_transition_name_nn
not null,
workflow_key varchar(100)
constraint wf_transition_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
-- what role does this transition belong to
-- (only for user-triggered transitions)
role_key varchar(100),
-- so we can display transitions in some logical order --
sort_order integer
constraint wf_transition_order_ck
check (sort_order > 0),
trigger_type varchar(40)
constraint wf_transition_trigger_type_ck
check (trigger_type in
('','automatic','user','message','time')),
-- table constraints --
constraint wf_transition_pk
primary key (workflow_key, transition_key),
constraint wf_trans_wf_key_trans_name_un
unique (workflow_key, transition_name),
constraint wf_transition_role_fk
foreign key (workflow_key,role_key) references wf_roles(workflow_key,role_key)
/* We don't do on delete cascade here, because that would mean that
* when a role is deleted, the transitions associated with that role would be deleted, too */
);
comment on table wf_transitions is '
The squares in the petri net. The things that somebody (or something) actually does.
';
create table wf_arcs (
workflow_key varchar(100)
constraint wf_ts_arc_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
transition_key varchar(100),
place_key varchar(100),
-- direction is relative to the transition
direction varchar(3)
constraint wf_arc_direction_ck
check (direction in ('','in','out')),
/* Must be satisfied for the arc to be traveled by a token
* This is the name of a PL/SQL function to execute, which must return t or f
* Signature: (case_id in integer, workflow_key in varchar, transition_key in varchar2,
* place_key in varchar, direction in varchar2, custom_arg in varchar2)
* return char(1)
*/
guard_callback varchar(100),
guard_custom_arg text,
guard_description varchar(500),
-- table constraints --
constraint wf_arc_pk
primary key (workflow_key, transition_key, place_key, direction),
constraint wf_arc_guard_on_in_arc_ck
check (guard_callback = '' or direction = 'out'),
constraint wf_arc_transition_fk
foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key)
on delete cascade,
constraint wf_arc_place_fk
foreign key (workflow_key, place_key) references wf_places(workflow_key, place_key)
on delete cascade
);
create index wf_arcs_wf_key_trans_key_idx on wf_arcs(workflow_key, transition_key);
create index wf_arcs_wf_key_place_key_idx on wf_arcs(workflow_key, place_key);
comment on table wf_arcs is '
The arcs of the workflow petri net.
Arcs always go between a transition and a place.
The direction is relative to the transition here, i.e.
in means it goes into the transition, out means it goes
away from the transition.
';
create table wf_transition_attribute_map (
workflow_key varchar(100)
constraint wf_trans_attr_map_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
transition_key varchar(100),
-- so the user can decide in what order the attributes should be presented
sort_order integer not null,
attribute_id integer
constraint wf_trans_attr_map_attribute_fk
references acs_attributes,
-- table constraints --
constraint wf_trans_attr_map_pk
primary key (workflow_key, transition_key, attribute_id),
constraint wf_trans_attr_map_trans_fk
foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key)
on delete cascade
);
comment on table wf_transition_attribute_map is '
The workflow attributes that should be set when
the given transition is fired.
';
create table wf_transition_role_assign_map (
workflow_key varchar(100)
constraint wf_role_asgn_map_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
transition_key varchar(100),
assign_role_key varchar(100),
-- table constraints --
constraint wf_role_asgn_map_pk
primary key (workflow_key, transition_key, assign_role_key),
constraint wf_role_asgn_map_trans_fk
foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key)
on delete cascade,
constraint wf_tr_role_asgn_map_asgn_fk
foreign key (workflow_key, assign_role_key) references wf_roles(workflow_key, role_key)
on delete cascade
);
create index wf_role_asgn_map_wf_trans_idx on wf_transition_role_assign_map(workflow_key, transition_key);
create index wf_role_asgn_map_wf_as_tr_idx on wf_transition_role_assign_map(workflow_key, assign_role_key);
comment on table wf_transition_role_assign_map is '
When part of the output of one task is to assign users to a role,
specify that this is the case by inserting a row here.
';
comment on column wf_transition_role_assign_map.transition_key is '
transition_key is the assigning transition.
';
comment on column wf_transition_role_assign_map.assign_role_key is '
assign_role_key is the role being assigned a user to.
';
/*
* Contexts
*/
create table wf_contexts (
context_key varchar(100)
constraint wf_context_pk
primary key,
context_name varchar(100)
constraint wf_contexts_context_name_nn
not null
constraint wf_contexts_context_name_un
unique
);
comment on table wf_contexts is '
The context of a workflow holds everything that''s not directly
part of the Petri Net structure, the stuff that''s likely to
be changed as the workflow is applied in a real business, and that
you will want to customize across different departments of the
same business. It includes assignments of transitions to parties,
the call-backs, etc.
';
/*
* Insert a default context that all new cases will use if nothing else
* is defined
*/
insert into wf_contexts (context_key, context_name) values ('default', 'Default Context');
create table wf_context_workflow_info (
context_key varchar(100)
constraint wf_context_wf_context_fk
references wf_contexts
on delete cascade,
workflow_key varchar(100)
constraint wf_context_wf_workflow_fk
references wf_workflows
on delete cascade,
/* The principal is the user/party that sends out email assignment notifications
* And receives email when a task becomes unassigned (for more than x minutes?)
*/
principal_party integer
constraint wf_context_wf_principal_fk
references parties
on delete set null,
-- table constraints --
constraint wf_context_workflow_pk
primary key (context_key, workflow_key)
);
comment on table wf_context_workflow_info is '
Holds context-dependent information about the workflow, specifically the
principal user.
';
create table wf_context_transition_info (
context_key varchar(100)
constraint wf_context_trans_context_fk
references wf_contexts,
workflow_key varchar(100)
constraint wf_context_trans_workflow_fk
references wf_workflows,
transition_key varchar(100),
/* information for the transition in the context */
/* The integer of minutes this task is estimated to take */
estimated_minutes integer,
/* Instructions for how to complete the task. Will be displayed on the task page. */
instructions text,
/*
* Will be called when the transition is enabled/fired.
* signature: (case_id in integer, transition_key in varchar, custom_arg in varchar2)
*/
enable_callback varchar(100),
enable_custom_arg text,
fire_callback varchar(100),
fire_custom_arg text,
/*
* Must return the date that the timed transition should fire
* Will be called when the transition is enabled
* signature: (case_id in integer, transition_key in varchar, custom_arg in varchar2) return date
*/
time_callback varchar(100),
time_custom_arg text,
/*
* Returns the deadline for this task.
* Will be called when the transition becomes enabled
* Signature: (case_id in integer, transition_key in varchar, custom_arg in varchar2) return date
*/
deadline_callback varchar(100),
deadline_custom_arg text,
/* The name of an attribute that holds the deadline */
deadline_attribute_name varchar(100),
/*
* Must return the date that the user's hold on the task times out.
* called when the user starts the task.
* signature: (case_id in integer, transition_key in varchar, custom_arg in varchar2) return date
*/
hold_timeout_callback varchar(100),
hold_timeout_custom_arg text,
/*
* Notification callback
* Will be called when a notification is sent i.e., when a transition is enabled,
* or assignment changes.
* signature: (task_id in integer,
* custom_arg in varchar,
* party_to in integer,
* party_from in out integer,
* subject in out varchar,
* body in out varchar)
*/
notification_callback varchar(100),
notification_custom_arg text,
/*
* Callback to handle unassigned tasks.
* Will be called when an enabled task becomes unassigned.
* Signature: (task_id in number, custom_arg in varchar2)
*/
unassigned_callback varchar(100),
unassigned_custom_arg text,
-- table constraints --
constraint wf_context_trans_trans_fk
foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key)
on delete cascade,
constraint wf_context_transition_pk
primary key (context_key, workflow_key, transition_key)
);
create index wf_ctx_trans_wf_trans_idx on wf_context_transition_info(workflow_key, transition_key);
comment on table wf_context_transition_info is '
This table holds information that pertains to a transition in a specific context.
It will specifically hold
';
create table wf_context_role_info (
context_key varchar(100)
constraint wf_context_role_context_fk
references wf_contexts(context_key)
on delete cascade,
workflow_key varchar(100)
constraint wf_context_role_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
role_key varchar(100),
/*
* Callback to programatically assign a role.
* Must call wordflow_case.*_role_assignment to make the assignments.
* Will be called when a transition for that role becomes enabled
* signature: (role_key in varchar2, custom_arg in varchar2)
*/
assignment_callback varchar(100),
assignment_custom_arg varchar(4000),
-- table constraints --
constraint wf_context_role_role_fk
foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key)
on delete cascade,
constraint wf_context_role_info_pk
primary key (context_key, workflow_key, role_key)
);
comment on table wf_context_role_info is '
This table holds context-dependent info for roles, currently only the assignment callback
';
create table wf_context_task_panels (
context_key varchar(100) not null
constraint wf_context_panels_context_fk
references wf_contexts(context_key)
on delete cascade,
workflow_key varchar(100) not null
constraint wf_context_panels_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
transition_key varchar(100) not null,
sort_order integer not null,
header varchar(200) not null,
template_url varchar(500) not null,
/* Display this panel in place of the action panel */
overrides_action_p char(1) default 'f'
constraint wf_context_panels_ovrd_p_ck
check (overrides_action_p in ('t','f')),
/* Display this panel only when the task has been started (and not finished) */
only_display_when_started_p char(1) default 'f'
constraint wf_context_panels_display_p_ck
check (only_display_when_started_p in ('t','f')),
overrides_both_panels_p char(1) default 'f'
constraint wf_context_panels_ovverides_both_ck
check (overrides_both_panels_p in ('t','f')),
-- table constraints --
constraint wf_context_panels_trans_fk
foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key)
on delete cascade,
constraint wf_context_panels_pk
primary key (context_key, workflow_key, transition_key, sort_order)
);
create index wf_ctx_panl_workflow_trans_idx on wf_context_task_panels(workflow_key, transition_key);
comment on table wf_context_task_panels is '
Holds information about the panels to be displayed on the task page.
';
create table wf_context_assignments (
context_key varchar(100)
constraint wf_context_assign_context_fk
references wf_contexts(context_key)
on delete cascade,
workflow_key varchar(100)
constraint wf_context_assign_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
role_key varchar(100),
party_id integer
constraint wf_context_assign_party_fk
references parties(party_id)
on delete cascade,
-- table constraints --
constraint wf_context_assign_pk
primary key (context_key, workflow_key, role_key, party_id),
constraint wf_context_assign_role_fk
foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key)
on delete cascade
);
create index wf_ctx_assg_workflow_trans_idx on wf_context_assignments(workflow_key, role_key);
comment on table wf_context_assignments is '
Static (default) per-context assignments of roles to parties.
';
------------------------------------
-- OPERATIONAL LEVEL OBJECTS
------------------------------------
create table wf_cases (
case_id integer
constraint wf_cases_pk
primary key
constraint wf_cases_acs_object_fk
references acs_objects(object_id)
on delete cascade,
workflow_key varchar(100)
constraint wf_cases_workflow_fk
references wf_workflows(workflow_key)
on delete cascade,
context_key varchar(100)
constraint wf_cases_context_fk
references wf_contexts(context_key)
on delete cascade,
object_id integer
constraint wf_cases_object_fk
references acs_objects(object_id)
on delete cascade,
-- a toplevel state of the case
state varchar(40)
default 'created'
constraint wf_cases_state_ck
check (state in ('created', 'active', 'suspended', 'canceled', 'finished'))
);
create index wf_cases_workflow_key_idx on wf_cases(workflow_key);
create index wf_cases_context_key_idx on wf_cases(context_key);
create index wf_cases_object_id_idx on wf_cases(object_id);
comment on table wf_cases is '
The instance of a process, e.g. the case of publishing one article,
the case of handling one insurance claim, the case of handling
one ecommerce order, of fixing one ticket-tracker ticket.
';
comment on column wf_cases.object_id is '
A case is generally about some other object, e.g., an insurance claim, an article,
a ticket, an order, etc. This is the place to store the reference to that object.
It is not uncommong to have more than one case for the same object, e.g., we might
have one process for evaluating and honoring an insurance claim, and another for archiving
legal information about a claim.
';
create table wf_case_assignments (
case_id integer
constraint wf_case_assign_fk
references wf_cases(case_id)
on delete cascade,
workflow_key varchar(100),
role_key varchar(100),
party_id integer
constraint wf_case_assign_party_fk
references parties(party_id)
on delete cascade,
-- table constraints --
constraint wf_case_assign_pk
primary key (case_id, role_key, party_id),
constraint wf_case_assign_role_fk
foreign key (workflow_key, role_key) references wf_roles(workflow_key, role_key)
on delete cascade
);
create index wf_case_assgn_party_idx on wf_case_assignments(party_id);
comment on table wf_case_assignments is '
Manual per-case assignments of roles to parties.
';
create table wf_case_deadlines (
case_id integer
constraint wf_case_deadline_fk
references wf_cases(case_id)
on delete cascade,
workflow_key varchar(100),
transition_key varchar(100),
deadline timestamptz
constraint wf_case_deadline_nn
not null,
-- table constraints --
constraint wf_case_deadline_pk
primary key (case_id, transition_key),
constraint wf_case_deadline_trans_fk
foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key)
on delete cascade
);
comment on table wf_case_deadlines is '
Manual deadlines for the individual transitions (tasks) on a per-case basis.
';
create sequence t_wf_task_id_seq;
create view wf_task_id_seq as
select nextval('t_wf_task_id_seq') as nextval;
create table wf_tasks (
task_id integer
constraint wf_task_pk
primary key,
case_id integer
constraint wf_task_case_fk
references wf_cases
on delete cascade,
workflow_key varchar(100)
constraint wf_task_workflow_fk
references wf_workflows(workflow_key),
transition_key varchar(100),
/* Information about the task */
state varchar(40)
default 'enabled'
constraint wf_task_state_ck
check (state in ('enabled','started','canceled',
'finished','overridden')),
enabled_date timestamptz default now(),
started_date timestamptz,
canceled_date timestamptz,
finished_date timestamptz,
overridden_date timestamptz,
/* -- TIME transition info */
trigger_time timestamptz,
/* -- USER transition info */
deadline timestamptz,
estimated_minutes integer,
holding_user integer
constraint wf_task_holding_user_fk
references users(user_id)
on delete cascade,
hold_timeout timestamptz,
-- table constraints --
constraint wf_task_transition_fk
foreign key (workflow_key, transition_key) references wf_transitions(workflow_key, transition_key)
);
create index wf_tasks_case_id_idx on wf_tasks(case_id);
create index wf_tasks_holding_user_idx on wf_tasks(holding_user);
comment on table wf_tasks is '
The tasks that need to be done, who can do it, and what state it''s in.
A task is the instance of a transition.
';
create table wf_task_assignments (
task_id integer
constraint wf_task_assign_task_fk
references wf_tasks(task_id)
on delete cascade,
party_id integer
constraint wf_task_party_fk
references parties(party_id)
on delete cascade,
-- table constraints --
constraint wf_task_assignments_pk
primary key (task_id, party_id)
);
create index wf_task_asgn_party_id_idx on wf_task_assignments(party_id);
create sequence t_wf_token_id_seq;
create view wf_token_id_seq as
select nextval('t_wf_token_id_seq') as nextval;
create table wf_tokens (
token_id integer
constraint wf_token_pk
primary key,
case_id integer
constraint wf_token_workflow_instance_fk
references wf_cases(case_id)
on delete cascade,
workflow_key varchar(100)
constraint wf_token_workflow_fk
references wf_workflows(workflow_key),
-- a token must always be in some place
place_key varchar(100),
state varchar(40) default 'free'
constraint wf_tokens_state_ck
check (state in ('free', 'locked', 'canceled', 'consumed')),
-- when the token is locked, by which task
locked_task_id integer
constraint wf_token_task_fk
references wf_tasks(task_id),
-- info on state changes
produced_date timestamptz default current_timestamp,
locked_date timestamptz,
canceled_date timestamptz,
consumed_date timestamptz,
produced_journal_id integer
constraint wf_token_produced_journal_fk
references journal_entries(journal_id),
locked_journal_id integer
constraint wf_token_locked_journal_fk
references journal_entries(journal_id),
canceled_journal_id integer
constraint wf_token_canceled_journal_fk
references journal_entries(journal_id),
consumed_journal_id integer
constraint wf_token_consumed_journal_fk
references journal_entries(journal_id),
-- table constraints --
constraint wf_token_place_fk
foreign key (workflow_key, place_key) references wf_places(workflow_key, place_key)
);
create index wf_tokens_case_id_idx on wf_tokens(case_id);
comment on table wf_tokens is '
Where the tokens currently are, and what task is laying hands on it, if any.
A token is sort of the instance of a place, except there''ll be one row here per
token, and there can be more than one token per place.
';
/* Should evetually be done by acs_objects automatically */
create table wf_attribute_value_audit (
case_id integer
constraint wf_attr_val_audit_case_fk
references wf_cases(case_id)
on delete cascade,
attribute_id integer
constraint wf_attr_val_audit_attr_fk
references acs_attributes(attribute_id)
on delete cascade,
journal_id integer
constraint wf_attr_val_audit_journal_fk
references journal_entries(journal_id),
attr_value text,
-- table constraints --
constraint wf_attr_val_audit_pk
primary key (case_id, attribute_id, journal_id)
);
create index wf_attr_val_aud_attr_id_idx on wf_attribute_value_audit(attribute_id);
comment on table wf_attribute_value_audit is '
This table holds all the attribute values that has been set,
so we can track changes over the lifetime of a case.
';
/*
* This is the cartesian product of transitions and contexts.
* We need this in order to compute the following wf_transition_info view,
* because Oracle won't let us outer join against more than one table.
*/
create view wf_transition_contexts as
select
t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.role_key,
c.context_key,
c.context_name
from
wf_transitions t,
wf_contexts c;
/*
* Returns all the information stored about a certain transition
* in all contexts. You'll usually want to use this with a
* "where context = " clause.
*/
create view wf_transition_info as
select
t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.context_key,
t.role_key,
ct.estimated_minutes,
ct.instructions,
ct.enable_callback,
ct.enable_custom_arg,
ct.fire_callback,
ct.fire_custom_arg,
ct.time_callback,
ct.time_custom_arg,
ct.deadline_callback,
ct.deadline_custom_arg,
ct.deadline_attribute_name,
ct.hold_timeout_callback,
ct.hold_timeout_custom_arg,
ct.notification_callback,
ct.notification_custom_arg,
ct.unassigned_callback,
ct.unassigned_custom_arg
from
wf_transition_contexts t
LEFT OUTER JOIN wf_context_transition_info ct ON (
ct.workflow_key = t.workflow_key and
ct.transition_key = t.transition_key and
ct.context_key = t.context_key
);
/*
* Returns all the information stored about a certain role
* in all contexts. You'll usually want to use this with a
* "where context = " clause.
*/
create view wf_role_info as
select r.role_key,
r.role_name,
r.workflow_key,
c.context_key,
cr.assignment_callback,
cr.assignment_custom_arg
from
wf_contexts c,
wf_roles r
LEFT OUTER JOIN wf_context_role_info cr ON (
cr.workflow_key = r.workflow_key
and cr.role_key = r.role_key
)
where
cr.context_key = c.context_key;
/*
* This view makes it easy to get the input/output places of a transition
*/
create view wf_transition_places as
select a.workflow_key,
t.transition_key,
p.place_key,
p.place_name,
p.sort_order,
a.direction,
a.guard_callback,
a.guard_custom_arg,
a.guard_description
from
wf_arcs a,
wf_places p,
wf_transitions t
where
a.transition_key = t.transition_key
and a.workflow_key = t.workflow_key
and p.place_key = a.place_key
and p.workflow_key = a.workflow_key;
/*
* This view returns information about all currently enabled transitions.
* It does not include transitions that are started. This information, along
* with additional, dynamic information, such as the user assignment or the
* time a timed transition triggers, is then stored in wf_tasks.
*
* Contrary to wf_tasks, this is authoritative, in that it queries
* the actual state of the workflow net.
*
* The logic behind this view is: All transitions in all cases, for which
* there does not exists a place for which there is not a free token.
*/
create view wf_enabled_transitions as
select
c.case_id,
t.transition_key,
t.transition_name,
t.workflow_key,
t.sort_order,
t.trigger_type,
t.context_key,
t.role_key,
t.enable_callback,
t.enable_custom_arg,
t.fire_callback,
t.fire_custom_arg,
t.time_callback,
t.time_custom_arg,
t.deadline_callback,
t.deadline_custom_arg,
t.deadline_attribute_name,
t.hold_timeout_callback,
t.hold_timeout_custom_arg,
t.notification_callback,
t.notification_custom_arg,
t.estimated_minutes,
t.instructions,
t.unassigned_callback,
t.unassigned_custom_arg
from
wf_transition_info t,
wf_cases c
where
t.workflow_key = c.workflow_key
and t.context_key = c.context_key
and c.state = 'active'
and not exists (
select tp.place_key
from wf_transition_places tp
where tp.transition_key = t.transition_key
and tp.workflow_key = t.workflow_key
and tp.direction = 'in'
and not exists
(select tk.token_id
from wf_tokens tk
where tk.place_key = tp.place_key
and tk.case_id = c.case_id
and tk.state = 'free'
)
);
/*
* This view joins wf_tasks with the parties data model to figure out who can perform the tasks.
* It should contain one row per ( user x task )
*/
/* Replaced 'unique' with 'distinct', because Stas had problems with Oracle behaving mysteriously */
create view wf_user_tasks as
select distinct
ta.task_id,
ta.case_id,
ta.workflow_key,
ta.transition_key,
tr.transition_name,
ta.enabled_date,
ta.started_date,
u.user_id,
ta.state,
ta.holding_user,
ta.hold_timeout,
ta.deadline,
ta.estimated_minutes
from
wf_tasks ta,
wf_task_assignments tasgn,
wf_cases c,
wf_transition_info tr,
party_approved_member_map m,
users u
where
ta.state in ( 'enabled','started')
and c.case_id = ta.case_id
and c.state = 'active'
and tr.transition_key = ta.transition_key
and tr.workflow_key = ta.workflow_key
and tr.trigger_type = 'user'
and tr.context_key = c.context_key
and tasgn.task_id = ta.task_id
and m.party_id = tasgn.party_id
and u.user_id = m.member_id;
acs-workflow-master/sql/postgresql/wf-core-drop.sql 0000664 0000000 0000000 00000004206 14575002472 0023024 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/wf-core-drop.sql
--
-- Drops the data model and views for the workflow package.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
/* Drop all cases and all workflows */
create function inline_0 () returns integer as $$
declare
workflow_rec record;
begin
for workflow_rec in
select w.workflow_key, t.table_name
from wf_workflows w, acs_object_types t
where t.object_type = w.workflow_key
LOOP
PERFORM workflow__delete_cases(workflow_rec.workflow_key);
execute 'drop table if exists ' || workflow_rec.table_name;
PERFORM workflow__drop_workflow(workflow_rec.workflow_key);
end loop;
return null;
end;$$ language 'plpgsql';
select inline_0 ();
drop function inline_0 ();
/* Sequences */
drop sequence if exists t_wf_task_id_seq;
drop sequence if exists t_wf_token_id_seq;
/* Views */
drop view if exists wf_task_id_seq;
drop view if exists wf_token_id_seq;
drop view if exists wf_user_tasks;
drop view if exists wf_enabled_transitions;
drop view if exists wf_transition_places;
drop view if exists wf_role_info;
drop view if exists wf_transition_info;
drop view if exists wf_transition_contexts;
/* Operational level */
drop table if exists wf_attribute_value_audit;
drop table if exists wf_tokens;
drop table if exists wf_task_assignments;
drop table if exists wf_tasks;
drop table if exists wf_case_assignments;
drop table if exists wf_case_deadlines;
drop table if exists wf_cases;
/* Context level */
drop table if exists wf_context_assignments;
drop table if exists wf_context_task_panels;
drop table if exists wf_context_role_info;
drop table if exists wf_context_transition_info;
drop table if exists wf_context_workflow_info;
drop table if exists wf_contexts;
/* Knowledge Level */
drop table if exists wf_transition_role_assign_map;
drop table if exists wf_transition_attribute_map;
drop table if exists wf_arcs;
drop table if exists wf_transitions;
drop table if exists wf_roles;
drop table if exists wf_places;
drop table if exists wf_workflows;
/* acs_object_type */
select acs_object_type__drop_type(
'workflow',
't'
);
acs-workflow-master/sql/postgresql/workflow-case-package-body.sql 0000664 0000000 0000000 00000203665 14575002472 0025641 0 ustar 00root root 0000000 0000000 -- create or replace package body workflow_case
-- function new
create or replace function workflow_case__new (integer,varchar,varchar,integer,timestamptz,integer,varchar)
returns integer as $$
declare
new__case_id alias for $1; -- default null
new__workflow_key alias for $2;
new__context_key alias for $3; -- default null
new__object_id alias for $4;
new__creation_date alias for $5; -- default now()
new__creation_user alias for $6; -- default null
new__creation_ip alias for $7; -- default null
v_case_id integer;
v_workflow_case_table varchar;
v_context_key_for_query varchar;
begin
if new__context_key = '' or new__context_key is null then
v_context_key_for_query := 'default';
else
v_context_key_for_query := new__context_key;
end if;
/* insert a row into acs_objects */
v_case_id := acs_object__new(
new__case_id,
new__workflow_key,
new__creation_date,
new__creation_user,
new__creation_ip,
null
);
/* insert the case in to the general wf_cases table */
insert into wf_cases
(case_id, workflow_key, context_key, object_id, state)
values
(v_case_id, new__workflow_key, v_context_key_for_query, new__object_id, 'created');
/* insert the case into the workflow-specific cases table */
select table_name into v_workflow_case_table
from acs_object_types
where object_type = new__workflow_key;
execute 'insert into ' || v_workflow_case_table || ' (case_id) values (' || v_case_id || ')';
return v_case_id;
end;$$ language 'plpgsql';
-- procedure add_manual_assignment
create or replace function workflow_case__add_manual_assignment (integer,varchar,integer)
returns integer as $$
declare
add_manual_assignment__case_id alias for $1;
add_manual_assignment__role_key alias for $2;
add_manual_assignment__party_id alias for $3;
v_workflow_key varchar;
v_num_rows integer;
begin
select count(*) into v_num_rows
from wf_case_assignments
where case_id = add_manual_assignment__case_id
and role_key = add_manual_assignment__role_key
and party_id = add_manual_assignment__party_id;
if v_num_rows = 0 then
select workflow_key into v_workflow_key
from wf_cases
where case_id = add_manual_assignment__case_id;
insert into wf_case_assignments (
case_id,
workflow_key,
role_key,
party_id
) values (
add_manual_assignment__case_id,
v_workflow_key,
add_manual_assignment__role_key,
add_manual_assignment__party_id
);
end if;
return 0;
end;$$ language 'plpgsql';
-- procedure remove_manual_assignment
create or replace function workflow_case__remove_manual_assignment (integer,varchar,integer)
returns integer as $$
declare
remove_manual_assignment__case_id alias for $1;
remove_manual_assignment__role_key alias for $2;
remove_manual_assignment__party_id alias for $3;
v_workflow_key varchar;
begin
select workflow_key
into v_workflow_key
from wf_cases
where case_id = remove_manual_assignment__case_id;
delete
from wf_case_assignments
where workflow_key = v_workflow_key
and case_id = remove_manual_assignment__case_id
and role_key = remove_manual_assignment__role_key
and party_id = remove_manual_assignment__party_id;
return 0;
end;$$ language 'plpgsql';
-- procedure clear_manual_assignments
create or replace function workflow_case__clear_manual_assignments (integer,varchar)
returns integer as $$
declare
clear_manual_assignments__case_id alias for $1;
clear_manual_assignments__role_key alias for $2;
v_workflow_key varchar;
begin
select workflow_key
into v_workflow_key
from wf_cases
where case_id = clear_manual_assignments__case_id;
delete
from wf_case_assignments
where workflow_key = v_workflow_key
and case_id = clear_manual_assignments__case_id
and role_key = clear_manual_assignments__role_key;
return 0;
end;$$ language 'plpgsql';
-- procedure start_case
create or replace function workflow_case__start_case (integer,integer,varchar,varchar)
returns integer as $$
declare
start_case__case_id alias for $1;
start_case__creation_user alias for $2; -- default null
start_case__creation_ip alias for $3; -- default null
start_case__msg alias for $4; -- default null
v_journal_id integer;
begin
/* Add an entry to the journal */
v_journal_id := journal_entry__new(
null,
start_case__case_id,
'case start',
'#acs-workflow.Case_started#',
now(),
start_case__creation_user,
start_case__creation_ip,
start_case__msg
);
update wf_cases
set state = 'active'
where case_id = start_case__case_id;
PERFORM workflow_case__add_token (
start_case__case_id,
'start',
v_journal_id
);
-- Turn the wheels
PERFORM workflow_case__sweep_automatic_transitions (
start_case__case_id,
v_journal_id
);
return 0;
end;$$ language 'plpgsql';
-- procedure delete
create or replace function workflow_case__delete (integer)
returns integer as $$
declare
delete__case_id alias for $1;
v_workflow_case_table varchar;
begin
/* delete attribute_value_audit, tokens, tasks */
delete from wf_attribute_value_audit
where case_id = delete__case_id;
delete from wf_case_assignments
where case_id = delete__case_id;
delete from wf_case_deadlines
where case_id = delete__case_id;
delete from wf_tokens
where case_id = delete__case_id;
delete from wf_task_assignments
where task_id in (
select task_id
from wf_tasks
where case_id = delete__case_id
);
delete from wf_tasks
where case_id = delete__case_id;
/* delete the journal */
PERFORM journal_entry__delete_for_object(delete__case_id);
/* delete from the workflow-specific cases table */
select table_name into v_workflow_case_table
from acs_object_types ot, wf_cases c
where c.case_id = delete__case_id
and object_type = c.workflow_key;
execute 'delete from ' || v_workflow_case_table || ' where case_id = ' || delete__case_id;
/* delete from the generic cases table */
delete from wf_cases where case_id = delete__case_id;
/* delete from acs-objects */
PERFORM acs_object__delete(delete__case_id);
return 0;
end;$$ language 'plpgsql';
-- procedure suspend
create or replace function workflow_case__suspend (integer,integer,varchar,varchar)
returns integer as $$
declare
suspend__case_id alias for $1;
suspend__user_id alias for $2; -- default null
suspend__ip_address alias for $3; -- default null
suspend__msg alias for $4; -- default null
v_state varchar;
v_journal_id integer;
begin
select state into v_state
from wf_cases
where case_id = suspend__case_id;
if v_state != 'active' then
raise EXCEPTION '-20000: Only active cases can be suspended';
end if;
/* Add an entry to the journal */
v_journal_id := journal_entry__new(
null,
suspend__case_id,
'case suspend',
'case suspended',
now(),
suspend__user_id,
suspend__ip_address,
suspend__msg
);
update wf_cases
set state = 'suspended'
where case_id = suspend__case_id;
return 0;
end;$$ language 'plpgsql';
-- procedure resume
create or replace function workflow_case__resume (integer,integer,varchar,varchar)
returns integer as $$
declare
resume__case_id alias for $1;
resume__user_id alias for $2; -- default null
resume__ip_address alias for $3; -- default null
resume__msg alias for $4; -- default null
v_state varchar;
v_journal_id integer;
begin
select state into v_state
from wf_cases
where case_id = resume__case_id;
if v_state != 'suspended' and v_state != 'canceled' then
raise EXCEPTION '-20000: Only suspended or canceled cases can be resumed';
end if;
/* Add an entry to the journal */
v_journal_id := journal_entry__new(
null,
resume__case_id,
'case resume',
'case resumed',
now(),
resume__user_id,
resume__ip_address,
resume__msg
);
update wf_cases
set state = 'active'
where case_id = resume__case_id;
return 0;
end;$$ language 'plpgsql';
-- procedure cancel
create or replace function workflow_case__cancel (integer,integer,varchar,varchar)
returns integer as $$
declare
cancel__case_id alias for $1;
cancel__user_id alias for $2; -- default null
cancel__ip_address alias for $3; -- default null
cancel__msg alias for $4; -- default null
v_state varchar;
v_journal_id integer;
begin
select state into v_state
from wf_cases
where case_id = cancel__case_id;
if v_state != 'active' and v_state != 'suspended' then
raise EXCEPTION '-20000: Only active or suspended cases can be canceled';
end if;
/* Add an entry to the journal */
v_journal_id := journal_entry__new(
null,
cancel__case_id,
'case cancel',
'Case canceled',
now(),
cancel__user_id,
cancel__ip_address,
cancel__msg
);
update wf_cases
set state = 'canceled'
where case_id = cancel__case_id;
return 0;
end;$$ language 'plpgsql';
-- procedure fire_message_transition
create or replace function workflow_case__fire_message_transition (integer)
returns integer as $$
declare
fire_message_transition__task_id alias for $1;
v_case_id integer;
v_transition_name varchar;
v_trigger_type varchar;
v_journal_id integer;
begin
select t.case_id, tr.transition_name, tr.trigger_type
into v_case_id, v_transition_name, v_trigger_type
from wf_tasks t, wf_transitions tr
where t.task_id = fire_message_transition__task_id
and tr.workflow_key = t.workflow_key
and tr.transition_key = t.transition_key;
if v_trigger_type != 'message' then
raise EXCEPTION '-20000: Transition "%" is not message triggered', v_transition_name;
end if;
/* Add an entry to the journal */
v_journal_id := journal_entry__new (
null,
v_case_id,
'task ' || fire_message_transition__task_id || ' fire',
v_transition_name || ' fired',
now(),
null,
null,
null
);
PERFORM workflow_case__fire_transition_internal(
fire_message_transition__task_id,
v_journal_id
);
PERFORM workflow_case__sweep_automatic_transitions (
v_case_id,
v_journal_id
);
return 0;
end;$$ language 'plpgsql';
/*
* A wrapper for user tasks that uses the start/commit/cancel model for firing transitions.
* Returns journal_id.
*/
-- function begin_task_action
create or replace function workflow_case__begin_task_action (integer,varchar,varchar,integer,varchar)
returns integer as $$
declare
begin_task_action__task_id alias for $1;
begin_task_action__action alias for $2;
begin_task_action__action_ip alias for $3;
begin_task_action__user_id alias for $4;
begin_task_action__msg alias for $5; -- default null
v_state varchar;
v_journal_id integer;
v_case_id integer;
v_transition_name varchar;
v_num_rows integer;
begin
select state into v_state
from wf_tasks
where task_id = begin_task_action__task_id;
if begin_task_action__action = 'start' then
if v_state != 'enabled' then
raise EXCEPTION '-20000: Task is in state "%", but it must be in state "enabled" to be started.', v_state;
end if;
select case when count(*) = 0 then 0 else 1 end into v_num_rows
from wf_user_tasks
where task_id = begin_task_action__task_id
and user_id = begin_task_action__user_id;
if v_num_rows = 0 then
raise EXCEPTION '-20000: You are not assigned to this task.';
end if;
else if begin_task_action__action = 'finish' or begin_task_action__action = 'cancel' then
if v_state = 'started' then
/* Is this user the holding user? */
select case when count(*) = 0 then 0 else 1 end into v_num_rows
from wf_tasks
where task_id = begin_task_action__task_id
and holding_user = begin_task_action__user_id;
if v_num_rows = 0 then
raise EXCEPTION '-20000: You are not the user currently working on this task.';
end if;
else if v_state = 'enabled' then
if begin_task_action__action = 'cancel' then
raise EXCEPTION '-20000: You can only cancel a task in state "started", but this task is in state "%"', v_state;
end if;
/* Is this user assigned to this task? */
select case when count(*) = 0 then 0 else 1 end into v_num_rows
from wf_user_tasks
where task_id = begin_task_action__task_id
and user_id = begin_task_action__user_id;
if v_num_rows = 0 then
raise EXCEPTION '-20000: You are not assigned to this task.';
end if;
/* This task is finished without an explicit start.
* Store the user as the holding_user */
update wf_tasks
set holding_user = begin_task_action__user_id
where task_id = begin_task_action__task_id;
else
raise EXCEPTION '-20000: Task is in state "%", but it must be in state "enabled" or "started" to be finished', v_state;
end if; end if;
else if begin_task_action__action = 'comment' then
-- We currently allow anyone to comment on a task
-- (need this line because PL/SQL does not like empty if blocks)
v_num_rows := 0;
end if; end if; end if;
select t.case_id, tr.transition_name into v_case_id, v_transition_name
from wf_tasks t,
wf_transitions tr
where t.task_id = begin_task_action__task_id
and tr.workflow_key = t.workflow_key
and tr.transition_key = t.transition_key;
/* Insert a journal entry */
v_journal_id := journal_entry__new (
null,
v_case_id,
'task ' || begin_task_action__task_id || ' ' || begin_task_action__action,
v_transition_name || ' ' || begin_task_action__action,
now(),
begin_task_action__user_id,
begin_task_action__action_ip,
begin_task_action__msg
);
return v_journal_id;
end;$$ language 'plpgsql';
-- procedure end_task_action
create or replace function workflow_case__end_task_action (integer,varchar,integer)
returns integer as $$
declare
end_task_action__journal_id alias for $1;
end_task_action__action alias for $2;
end_task_action__task_id alias for $3;
v_user_id integer;
begin
select creation_user into v_user_id
from acs_objects
where object_id = end_task_action__journal_id;
/* Update the workflow state */
if end_task_action__action = 'start' then
PERFORM workflow_case__start_task(end_task_action__task_id,
v_user_id,
end_task_action__journal_id
);
else if end_task_action__action = 'finish' then
PERFORM workflow_case__finish_task(end_task_action__task_id,
end_task_action__journal_id
);
else if end_task_action__action = 'cancel' then
PERFORM workflow_case__cancel_task(end_task_action__task_id,
end_task_action__journal_id
);
else if end_task_action__action != 'comment' then
raise EXCEPTION '-20000: Unknown action "%"', end_task_action__action;
end if; end if; end if; end if;
return 0;
end;$$ language 'plpgsql';
-- function task_action
create or replace function workflow_case__task_action (integer,varchar,varchar,integer,varchar)
returns integer as $$
declare
task_action__task_id alias for $1;
task_action__action alias for $2;
task_action__action_ip alias for $3;
task_action__user_id alias for $4;
task_action__msg alias for $5; -- default null
v_journal_id integer;
begin
v_journal_id := workflow_case__begin_task_action (
task_action__task_id,
task_action__action,
task_action__action_ip,
task_action__user_id,
task_action__msg
);
PERFORM workflow_case__end_task_action (
v_journal_id,
task_action__action,
task_action__task_id
);
return v_journal_id;
end;$$ language 'plpgsql';
-- procedure set_attribute_value
create or replace function workflow_case__set_attribute_value (integer,varchar,varchar)
returns integer as $$
declare
set_attribute_value__journal_id alias for $1;
set_attribute_value__attribute_name alias for $2;
set_attribute_value__value alias for $3;
v_workflow_key varchar;
v_case_id integer;
v_attribute_id integer;
begin
select o.object_type, o.object_id into v_workflow_key, v_case_id
from journal_entries je, acs_objects o
where je.journal_id = set_attribute_value__journal_id
and o.object_id = je.object_id;
select attribute_id into v_attribute_id
from acs_attributes
where object_type = v_workflow_key
and attribute_name = set_attribute_value__attribute_name;
PERFORM acs_object__set_attribute (
v_case_id,
set_attribute_value__attribute_name,
set_attribute_value__value
);
insert into wf_attribute_value_audit
(case_id, attribute_id, journal_id, attr_value)
values
(v_case_id, v_attribute_id, set_attribute_value__journal_id,
set_attribute_value__value);
return 0;
end;$$ language 'plpgsql';
-- function get_attribute_value
create or replace function workflow_case__get_attribute_value (integer,varchar)
returns varchar as $$
declare
get_attribute_value__case_id alias for $1;
get_attribute_value__attribute_name alias for $2;
begin
return acs_object__get_attribute (
get_attribute_value__case_id,
get_attribute_value__attribute_name
);
end;$$ language 'plpgsql';
-- procedure add_task_assignment
create or replace function workflow_case__add_task_assignment (integer,integer,boolean)
returns integer as $$
declare
add_task_assignment__task_id alias for $1;
add_task_assignment__party_id alias for $2;
add_task_assignment__permanent_p alias for $3;
v_count integer;
v_workflow_key wf_workflows.workflow_key%TYPE;
v_context_key wf_contexts.context_key%TYPE;
v_case_id wf_cases.case_id%TYPE;
v_role_key wf_roles.role_key%TYPE;
v_transition_key wf_transitions.transition_key%TYPE;
v_notification_callback wf_context_transition_info.notification_callback%TYPE;
v_notification_custom_arg wf_context_transition_info.notification_custom_arg%TYPE;
callback_rec record;
v_assigned_user record;
begin
IF add_task_assignment__party_id is null THEN return 0; END IF;
-- get some needed information
select ta.case_id, ta.workflow_key, ta.transition_key, tr.role_key, c.context_key
into v_case_id, v_workflow_key, v_transition_key, v_role_key, v_context_key
from wf_tasks ta,
wf_transitions tr,
wf_cases c
where ta.task_id = add_task_assignment__task_id
and tr.workflow_key = ta.workflow_key
and tr.transition_key = ta.transition_key
and c.case_id = ta.case_id;
-- make the same assignment as a manual assignment
IF add_task_assignment__permanent_p = 't' and v_role_key is not null THEN
/* We do this up-front, because
* even though the user already had a task assignment,
* he might not have a case assignment.
*/
perform workflow_case__add_manual_assignment (
v_case_id,
v_role_key,
add_task_assignment__party_id
);
end if;
-- check that we do not hit the unique constraint
select count(*) into v_count
from wf_task_assignments
where task_id = add_task_assignment__task_id
and party_id = add_task_assignment__party_id;
if v_count > 0 then
return null;
end if;
-- get callback information
select notification_callback, notification_custom_arg into callback_rec
from wf_context_transition_info
where context_key = v_context_key
and workflow_key = v_workflow_key
and transition_key = v_transition_key;
if FOUND then
v_notification_callback := callback_rec.notification_callback;
v_notification_custom_arg := callback_rec.notification_custom_arg;
else
v_notification_callback := null;
v_notification_custom_arg := null;
end if;
-- notify any new assignees
for v_assigned_user in
select distinct u.user_id
from users u
where u.user_id not in (
select distinct u2.user_id
from wf_task_assignments tasgn2,
party_approved_member_map m2,
users u2
where tasgn2.task_id = add_task_assignment__task_id
and m2.party_id = tasgn2.party_id
and u2.user_id = m2.member_id)
and exists (
select 1
from party_approved_member_map m
where m.member_id = u.user_id
and m.party_id = add_task_assignment__party_id
)
LOOP
PERFORM workflow_case__notify_assignee (
add_task_assignment__task_id,
v_assigned_user.user_id,
v_notification_callback,
v_notification_custom_arg
);
end loop;
-- do the insert
insert into wf_task_assignments (
task_id,
party_id
) values (
add_task_assignment__task_id,
add_task_assignment__party_id
);
return 0;
end;$$ language 'plpgsql';
-- procedure remove_task_assignment
create or replace function workflow_case__remove_task_assignment (integer,integer,boolean)
returns integer as $$
declare
remove_task_assignment__task_id alias for $1;
remove_task_assignment__party_id alias for $2;
remove_task_assignment__permanent_p alias for $3;
v_num_assigned integer;
v_case_id integer;
v_role_key wf_roles.role_key%TYPE;
v_workflow_key varchar;
v_transition_key varchar;
v_context_key varchar;
callback_rec record;
begin
-- get some information
select ta.case_id, ta.transition_key, tr.role_key, ta.workflow_key, c.context_key
into v_case_id, v_transition_key, v_role_key, v_workflow_key, v_context_key
from wf_tasks ta, wf_transitions tr, wf_cases c
where ta.task_id = remove_task_assignment__task_id
and tr.workflow_key = ta.workflow_key
and tr.transition_key = ta.transition_key
and c.case_id = ta.case_id;
-- make the same assignment as a manual assignment
if remove_task_assignment__permanent_p = 't' then
perform workflow_case__remove_manual_assignment (
v_case_id,
v_role_key,
remove_task_assignment__party_id
);
end if;
-- now delete the row
delete
from wf_task_assignments
where task_id = remove_task_assignment__task_id
and party_id = remove_task_assignment__party_id;
-- check if the task now became unassigned
select count(*)
into v_num_assigned
from wf_task_assignments
where task_id = remove_task_assignment__task_id;
if v_num_assigned > 0 then
return 0;
end if;
-- yup, the task is now unassigned; fire the callback
select unassigned_callback, unassigned_custom_arg
into callback_rec
from wf_context_transition_info
where workflow_key = v_workflow_key
and context_key = v_context_key
and transition_key = v_transition_key;
if FOUND then
PERFORM workflow_case__execute_unassigned_callback (
callback_rec.unassigned_callback,
remove_task_assignment__task_id,
callback_rec.unassigned_custom_arg
);
end if;
return 0;
end;$$ language 'plpgsql';
-- procedure clear_task_assignments
create or replace function workflow_case__clear_task_assignments (integer,boolean)
returns integer as $$
declare
clear_task_assignments__task_id alias for $1;
clear_task_assignments__permanent_p alias for $2;
v_case_id integer;
v_transition_key varchar;
v_role_key wf_roles.role_key%TYPE;
v_workflow_key varchar;
v_context_key varchar;
v_callback varchar;
v_custom_arg varchar;
begin
-- get some information
select ta.case_id, ta.transition_key, tr.role_key, ta.workflow_key, c.context_key
into v_case_id, v_transition_key, v_role_key, v_workflow_key, v_context_key
from wf_tasks ta, wf_transitions tr, wf_cases c
where ta.task_id = clear_task_assignments__task_id
and tr.workflow_key = ta.workflow_key
and tr.transition_key = ta.transition_key
and c.case_id = ta.case_id;
-- make the unassignment stick as a manual assignment
if clear_task_assignments__permanent_p = 't' then
perform workflow_case__clear_manual_assignments (
v_case_id,
v_role_key
);
end if;
-- delete the rows
delete
from wf_task_assignments
where task_id = clear_task_assignments__task_id;
-- fire the unassigned callback
select unassigned_callback, unassigned_custom_arg
into v_callback, v_custom_arg
from wf_context_transition_info
where workflow_key = v_workflow_key
and context_key = v_context_key
and transition_key = v_transition_key;
PERFORM workflow_case__execute_unassigned_callback (
v_callback,
clear_task_assignments__task_id,
v_custom_arg
);
return 0;
end;$$ language 'plpgsql';
-- procedure set_case_deadline
create or replace function workflow_case__set_case_deadline (integer,varchar,timestamptz)
returns integer as $$
declare
set_case_deadline__case_id alias for $1;
set_case_deadline__transition_key alias for $2;
set_case_deadline__deadline alias for $3;
v_workflow_key wf_workflows.workflow_key%TYPE;
begin
-- delete the current deadline row
delete
from wf_case_deadlines
where case_id = set_case_deadline__case_id
and transition_key = set_case_deadline__transition_key;
if set_case_deadline__deadline is not null then
-- get some info
select workflow_key
into v_workflow_key
from wf_cases
where case_id = set_case_deadline__case_id;
-- insert new deadline row
insert into wf_case_deadlines (
case_id,
workflow_key,
transition_key,
deadline
) values (
set_case_deadline__case_id,
v_workflow_key,
set_case_deadline__transition_key,
set_case_deadline__deadline
);
end if;
return 0;
end;$$ language 'plpgsql';
-- procedure remove_case_deadline
create or replace function workflow_case__remove_case_deadline (integer,varchar)
returns integer as $$
declare
remove_case_deadline__case_id alias for $1;
remove_case_deadline__transition_key alias for $2;
begin
perform workflow_case__set_case_deadline (
remove_case_deadline__case_id,
remove_case_deadline__transition_key,
null
);
return 0;
end;$$ language 'plpgsql';
-- function evaluate_guard
create or replace function workflow_case__evaluate_guard (varchar,varchar,integer,varchar,varchar,varchar,varchar)
returns boolean as $$
declare
evaluate_guard__callback alias for $1;
evaluate_guard__custom_arg alias for $2;
evaluate_guard__case_id alias for $3;
evaluate_guard__workflow_key alias for $4;
evaluate_guard__transition_key alias for $5;
evaluate_guard__place_key alias for $6;
evaluate_guard__direction alias for $7;
v_guard_happy_p boolean;
v_rec record;
v_str text default '';
begin
if evaluate_guard__callback = '' or
evaluate_guard__callback is null then
-- null guard evaluates to true
return 't';
else
if evaluate_guard__callback = '#' then
return 'f';
else
v_str := 'select ' || evaluate_guard__callback
|| '(' ||
evaluate_guard__case_id || ',' ||
quote_literal(evaluate_guard__workflow_key) || ',' ||
quote_literal(evaluate_guard__transition_key) || ',' ||
quote_literal(evaluate_guard__place_key) || ',' ||
quote_literal(evaluate_guard__direction) || ',' ||
coalesce(quote_literal(evaluate_guard__custom_arg),'null') || ') as guard_happy_p';
raise notice 'str = %', v_str;
for v_rec in
execute v_str
LOOP
return v_rec.guard_happy_p;
end LOOP;
end if;
end if;
return null;
end;$$ language 'plpgsql';
-- procedure execute_transition_callback
create or replace function workflow_case__execute_transition_callback (varchar,varchar,integer,varchar)
returns integer as $$
declare
execute_transition_callback__callback alias for $1;
execute_transition_callback__custom_arg alias for $2;
execute_transition_callback__case_id alias for $3;
execute_transition_callback__transition_key alias for $4;
v_str text;
begin
if execute_transition_callback__callback != '' and execute_transition_callback__callback is not null then
v_str := 'select ' || execute_transition_callback__callback
|| '(' || execute_transition_callback__case_id || ',' ||
quote_literal(execute_transition_callback__transition_key) || ',' ||
coalesce(quote_literal(execute_transition_callback__custom_arg),'null') || ')';
execute v_str;
end if;
return 0;
end;$$ language 'plpgsql';
-- function execute_time_callback
create or replace function workflow_case__execute_time_callback (varchar,varchar,integer,varchar)
returns timestamptz as $$
declare
execute_time_callback__callback alias for $1;
execute_time_callback__custom_arg alias for $2;
execute_time_callback__case_id alias for $3;
execute_time_callback__transition_key alias for $4;
v_rec record;
v_str text;
v_result timestamptz;
begin
if execute_time_callback__callback = '' or execute_time_callback__callback is null then
return null;
end if;
v_str := 'select ' || execute_time_callback__callback || '(' ||
execute_time_callback__case_id || ',' ||
quote_literal(execute_time_callback__transition_key) || ',' ||
coalesce(quote_literal(execute_time_callback__custom_arg),'null') || ') as trigger_time';
for v_rec in execute v_str
LOOP
v_result := v_rec.trigger_time;
end LOOP;
RAISE NOTICE 'workflow_case__execute_time_callback: res=%, sql=%', v_result, v_str;
return v_result;
end;$$ language 'plpgsql';
-- function get_task_deadline
create or replace function workflow_case__get_task_deadline (varchar,varchar,varchar,integer,varchar)
returns timestamptz as $$
declare
get_task_deadline__callback alias for $1;
get_task_deadline__custom_arg alias for $2;
get_task_deadline__attribute_name alias for $3;
get_task_deadline__case_id alias for $4;
get_task_deadline__transition_key alias for $5;
v_deadline timestamptz;
v_rec record;
v_str varchar;
begin
/*
* 1. or if there is a row in wf_case_deadlines, we use that
* 2. if there is a callback, we execute that
* 3. otherwise, if there is an attribute, we use that
*/
/* wf_case_deadlines */
select deadline into v_deadline
from wf_case_deadlines
where case_id = get_task_deadline__case_id
and transition_key = get_task_deadline__transition_key;
if NOT FOUND then
if get_task_deadline__callback != '' and get_task_deadline__callback is not null then
/* callback */
v_str := 'select ' || get_task_deadline__callback || '(' ||
get_task_deadline__case_id || ',' ||
quote_literal(get_task_deadline__transition_key) || ',' ||
coalesce(quote_literal(get_task_deadline__custom_arg),'null') || ') as deadline';
for v_rec in execute v_str
LOOP
v_deadline := v_rec.deadline;
exit;
end LOOP;
else if get_task_deadline__attribute_name != '' and get_task_deadline__attribute_name is not null then
/* attribute */
v_deadline := acs_object__get_attribute (
get_task_deadline__case_id,
get_task_deadline__attribute_name
);
else
v_deadline := null;
end if; end if;
end if;
return v_deadline;
end;$$ language 'plpgsql';
-- function execute_hold_timeout_callback
create or replace function workflow_case__execute_hold_timeout_callback (varchar,varchar,integer,varchar)
returns timestamptz as $$
declare
execute_hold_timeout_callback__callback alias for $1;
execute_hold_timeout_callback__custom_arg alias for $2;
execute_hold_timeout_callback__case_id alias for $3;
execute_hold_timeout_callback__transition_key alias for $4;
v_hold_timeout timestamptz;
v_rec record;
v_str text;
begin
if execute_hold_timeout_callback__callback = '' or execute_hold_timeout_callback__callback is null then
return null;
end if;
v_str := 'select ' || execute_hold_timeout_callback__callback
|| '(' ||
execute_hold_timeout_callback__case_id || ',' ||
quote_literal(execute_hold_timeout_callback__transition_key) ||
',' ||
coalesce(quote_literal(execute_hold_timeout_callback__custom_arg),'null') || ') as hold_timeout';
for v_rec in execute v_str
LOOP
return v_rec.hold_timeout;
end LOOP;
return null;
end;$$ language 'plpgsql';
-- procedure execute_unassigned_callback
create or replace function workflow_case__execute_unassigned_callback (varchar,integer,varchar)
returns integer as $$
declare
callback alias for $1;
task_id alias for $2;
custom_arg alias for $3;
v_str text;
begin
if callback != '' and callback is not null then
v_str := 'select ' || callback
|| '(' || task_id || ',' ||
coalesce(quote_literal(custom_arg),'null')
|| ')';
execute v_str;
end if;
return 0;
end;$$ language 'plpgsql';
-- procedure set_task_assignments
create or replace function workflow_case__set_task_assignments (integer,varchar,varchar)
returns integer as $$
declare
set_task_assignments__task_id alias for $1;
set_task_assignments__callback alias for $2;
set_task_assignments__custom_arg alias for $3;
v_done_p boolean;
case_assignment_rec record;
context_assignment_rec record;
v_str text;
begin
/* Find out who to assign the given task to.
*
* 1. See if there are rows in wf_case_assignments.
* 2. If not, and a callback is defined, execute that.
* 3. Otherwise, grab the assignment from the workflow context.
*
* (We used to use the callback first, but that makes
* reassignment of tasks difficult.)
*/
v_done_p := 'f';
for case_assignment_rec in select party_id
from wf_case_assignments ca, wf_tasks t, wf_transitions tr
where t.task_id = set_task_assignments__task_id
and ca.case_id = t.case_id
and ca.role_key = tr.role_key
and tr.workflow_key = t.workflow_key
and tr.transition_key = t.transition_key
LOOP
v_done_p := 't';
PERFORM workflow_case__add_task_assignment (
set_task_assignments__task_id,
case_assignment_rec.party_id,
'f'
);
end loop;
if v_done_p != 't' then
if set_task_assignments__callback != '' and set_task_assignments__callback is not null then
v_str := 'select '|| set_task_assignments__callback || '(' ||
set_task_assignments__task_id || ',' ||
coalesce(quote_literal(set_task_assignments__custom_arg),'null') || ')';
execute v_str;
else
for context_assignment_rec in
select party_id
from wf_context_assignments ca, wf_cases c, wf_tasks t, wf_transitions tr
where t.task_id = set_task_assignments__task_id
and c.case_id = t.case_id
and ca.context_key = c.context_key
and ca.workflow_key = t.workflow_key
and ca.role_key = tr.role_key
and tr.workflow_key = t.workflow_key
and tr.transition_key = t.transition_key
LOOP
PERFORM workflow_case__add_task_assignment (
set_task_assignments__task_id,
context_assignment_rec.party_id,
'f'
);
end LOOP;
end if;
end if;
return 0;
end;$$ language 'plpgsql';
-- procedure add_token
create or replace function workflow_case__add_token (integer,varchar,integer)
returns integer as $$
declare
add_token__case_id alias for $1;
add_token__place_key alias for $2;
add_token__journal_id alias for $3;
v_token_id integer;
v_workflow_key varchar;
begin
select nextval('t_wf_token_id_seq') into v_token_id from dual;
select workflow_key into v_workflow_key
from wf_cases c
where c.case_id = add_token__case_id;
insert into wf_tokens
(token_id, case_id, workflow_key, place_key, state, produced_journal_id)
values (v_token_id, add_token__case_id, v_workflow_key, add_token__place_key,
'free', add_token__journal_id);
return 0;
end;$$ language 'plpgsql';
-- procedure lock_token
create or replace function workflow_case__lock_token (integer,varchar,integer,integer)
returns integer as $$
declare
lock_token__case_id alias for $1;
lock_token__place_key alias for $2;
lock_token__journal_id alias for $3;
lock_token__task_id alias for $4;
begin
-- FIXME: rownum
-- update wf_tokens
-- set state = 'locked',
-- locked_task_id = lock_token__task_id,
-- locked_date = now(),
-- locked_journal_id = lock_token__journal_id
-- where case_id = lock_token__case_id
-- and place_key = lock_token__place_key
-- and state = 'free'
-- and rownum = 1;
update wf_tokens
set state = 'locked',
locked_task_id = lock_token__task_id,
locked_date = now(),
locked_journal_id = lock_token__journal_id
where token_id = (select token_id
from wf_tokens
where case_id = lock_token__case_id
and place_key = lock_token__place_key
and state = 'free'
limit 1);
return 0;
end;$$ language 'plpgsql';
-- procedure release_token
create or replace function workflow_case__release_token (integer,integer)
returns integer as $$
declare
release_token__task_id alias for $1;
release_token__journal_id alias for $2;
token_rec record;
begin
/* Add a new token for each released one */
for token_rec in
select token_id,
case_id,
place_key
from wf_tokens
where state = 'locked'
and locked_task_id = release_token__task_id
LOOP
PERFORM workflow_case__add_token (
token_rec.case_id,
token_rec.place_key,
release_token__journal_id
);
end loop;
/* Mark the released ones canceled */
update wf_tokens
set state = 'canceled',
canceled_date = now(),
canceled_journal_id = release_token__journal_id
where state = 'locked'
and locked_task_id = release_token__task_id;
return 0;
end;$$ language 'plpgsql';
-- procedure consume_token
create or replace function workflow_case__consume_token (integer,varchar,integer,integer)
returns integer as $$
declare
consume_token__case_id alias for $1;
consume_token__place_key alias for $2;
consume_token__journal_id alias for $3;
consume_token__task_id alias for $4; -- default null
begin
if consume_token__task_id is null then
update wf_tokens
set state = 'consumed',
consumed_date = now(),
consumed_journal_id = consume_token__journal_id
where token_id = (select token_id
from wf_tokens
where case_id = consume_token__case_id
and place_key = consume_token__place_key
and state = 'free'
limit 1);
else
update wf_tokens
set state = 'consumed',
consumed_date = now(),
consumed_journal_id = consume_token__journal_id
where case_id = consume_token__case_id
and place_key = consume_token__place_key
and state = 'locked'
and locked_task_id = consume_token__task_id;
end if;
return 0;
end;$$ language 'plpgsql';
-- procedure sweep_automatic_transitions
create or replace function workflow_case__sweep_automatic_transitions (integer,integer)
returns integer as $$
declare
sweep_automatic_transitions__case_id alias for $1;
sweep_automatic_transitions__journal_id alias for $2;
v_done_p boolean:='f';
v_finished_p boolean;
task_rec record;
begin
RAISE NOTICE 'sweep_automatic_transitions(%,%)',
sweep_automatic_transitions__case_id, sweep_automatic_transitions__journal_id;
PERFORM workflow_case__enable_transitions(sweep_automatic_transitions__case_id);
while v_done_p != 't' loop
v_done_p := 't';
v_finished_p := workflow_case__finished_p (
sweep_automatic_transitions__case_id,
sweep_automatic_transitions__journal_id
);
if v_finished_p = 'f' then
for task_rec in
select task_id
from wf_tasks ta, wf_transitions tr
where tr.workflow_key = ta.workflow_key
and tr.transition_key = ta.transition_key
and tr.trigger_type = 'automatic'
and ta.state = 'enabled'
and ta.case_id = sweep_automatic_transitions__case_id
LOOP
PERFORM workflow_case__fire_transition_internal (
task_rec.task_id,
sweep_automatic_transitions__journal_id
);
v_done_p := 'f';
end loop;
PERFORM workflow_case__enable_transitions(sweep_automatic_transitions__case_id);
end if;
end loop;
return 0;
end;$$ language 'plpgsql';
-- function finished_p
create or replace function workflow_case__finished_p (integer,integer)
returns boolean as $$
declare
finished_p__case_id alias for $1;
finished_p__journal_id alias for $2;
v_case_state varchar;
v_token_id integer;
v_num_rows integer;
v_journal_id integer;
begin
select state into v_case_state
from wf_cases
where case_id = finished_p__case_id;
if v_case_state = 'finished' then
return 't';
else
/* Let us see if the case is actually finished, but just not marked so */
select case when count(*) = 0 then 0 else 1 end into v_num_rows
from wf_tokens
where case_id = finished_p__case_id
and place_key = 'end';
if v_num_rows = 0 then
return 'f';
else
/* There is a token in the end place.
* Count the total integer of tokens to make sure the wf is well-constructed.
*/
select case when count(*) = 0 then 0
when count(*) = 1 then 1
else 2
end into v_num_rows
from wf_tokens
where case_id = finished_p__case_id
and state in ('free', 'locked');
if v_num_rows > 1 then
raise EXCEPTION '-20000: The workflow net is misconstructed: Some parallel executions have not finished.';
end if;
/* Consume that token */
select token_id into v_token_id
from wf_tokens
where case_id = finished_p__case_id
and state in ('free', 'locked');
PERFORM workflow_case__consume_token (
finished_p__case_id,
'end',
finished_p__journal_id,
null
);
update wf_cases
set state = 'finished'
where case_id = finished_p__case_id;
/* Add an extra entry to the journal */
v_journal_id := journal_entry__new (
null,
finished_p__case_id,
'case finish',
'Case finished',
now(),
null,
null,
null
);
return 't';
end if;
end if;
end;$$ language 'plpgsql';
-- The next two functions are called periodically by a scheduled Tcl script.
create or replace function workflow_case__sweep_timed_transitions () returns integer as $$
declare
v_journal_id integer;
trans_rec record;
begin
for trans_rec in
select t.task_id, t.case_id, tr.transition_name
from wf_tasks t, wf_transitions tr
where trigger_time <= now()
and state = 'enabled'
and tr.workflow_key = t.workflow_key
and tr.transition_key = t.transition_key
LOOP
/* Insert an entry to the journal so people will know it fired */
v_journal_id := journal_entry__new (
null,
trans_rec.case_id,
'task ' || trans_rec.task_id || ' fire time',
trans_rec.transition_name || ' automatically finished',
now(),
null,
null,
'Timed transition fired.'
);
/* Fire the transition */
PERFORM workflow_case__fire_transition_internal (
trans_rec.task_id,
v_journal_id
);
/* Update the workflow internal state */
PERFORM workflow_case__sweep_automatic_transitions(
trans_rec.case_id,
v_journal_id
);
end loop;
return 0;
end;$$ language 'plpgsql';
create or replace function workflow_case__sweep_hold_timeout () returns integer as $$
declare
v_journal_id integer;
task_rec record;
begin
for task_rec in select t.task_id, t.case_id, tr.transition_name
from wf_tasks t, wf_transitions tr
where hold_timeout <= now()
and state = 'started'
and tr.workflow_key = t.workflow_key
and tr.transition_key = t.transition_key
LOOP
/* Insert an entry to the journal so people will know it was canceled */
v_journal_id := journal_entry__new (
null,
task_rec.case_id,
'task ' || task_rec.task_id || ' cancel timeout',
task_rec.transition_name || ' timed out',
now(),
null,
null,
'The hold of the user on the task timed out and the task was automatically canceled'
);
/* Cancel the task */
PERFORM workflow_case__cancel_task (
task_rec.task_id,
v_journal_id
);
end loop;
return 0;
end;$$ language 'plpgsql';
-- Lookup localized message for workflow notification
create or replace function workflow_case__notify_l10n_lookup (varchar,varchar,varchar,varchar,varchar,integer)
returns varchar as $$
declare
p_message_prefix alias for $1;
p_notification_type alias for $2;
p_workflow_key alias for $3;
p_transition_key alias for $4;
p_locale alias for $5;
p_include_l10n_link alias for $6;
v_key varchar;
v_message varchar;
v_system_url varchar;
v_url varchar;
begin
select apm__get_value((select package_id from apm_packages where package_key = 'acs-kernel'), 'SystemURL') into v_system_url;
-- ------------------------------------------------------------
-- Try with specific translation first
v_key := p_message_prefix || '_' || p_workflow_key || '_' || p_transition_key || '_' || p_notification_type;
v_message := acs_lang_lookup_message(p_locale, 'acs-workflow', v_key);
-- Fallback to more generic translation
IF substring(v_message from 1 for 7) = 'MISSING' THEN
v_key := p_message_prefix || '_' || p_workflow_key || '_' || p_transition_key;
v_message := acs_lang_lookup_message(p_locale, 'acs-workflow', v_key);
END IF;
-- Fallback to more generic translation
IF substring(v_message from 1 for 7) = 'MISSING' THEN
v_key := p_message_prefix || '_' || p_transition_key;
v_message := acs_lang_lookup_message(p_locale, 'acs-workflow', v_key);
END IF;
-- Fallback to more generic translation
IF substring(v_message from 1 for 7) = 'MISSING' THEN
v_key := p_message_prefix || '_' || p_transition_key;
v_message := acs_lang_lookup_message(p_locale, 'acs-workflow', v_key);
END IF;
-- Still no translation - create a message
IF p_include_l10n_link > 0 THEN
IF substring(v_message from 1 for 7) = 'MISSING' THEN
v_key := p_message_prefix || '_' || p_workflow_key || '_' || p_transition_key || '_' || p_notification_type;
v_url = v_system_url || '/acs-lang/admin/localized-message-new?package_key=acs-workflow&locale='||p_locale||'&message_key='||v_key;
v_message := E'Missing translation for message key\n\n'
|| E'Please visit the URL below with system administrator rights and create a translation\n'
|| v_url || E'\n\n'
|| E'Please also create a translation for the message subject by replacing the "Body" in the URL above with "Subject".'
|| E'\n\nSystem Administrator';
END IF;
END IF;
return v_message;
end;$$ language 'plpgsql';
-- Compatibility proc - to maintain API
create or replace function workflow_case__notify_assignee (integer,integer,varchar,varchar)
returns integer as $$
declare
notify_assignee__task_id alias for $1;
notify_assignee__user_id alias for $2;
notify_assignee__callback alias for $3;
notify_assignee__custom_arg alias for $4;
begin
return workflow_case__notify_assignee($1,$2,$3,$4,null);
end;$$ language 'plpgsql';
-- Send out notification emails to assignees of workflow transitions
create or replace function workflow_case__notify_assignee (integer,integer,varchar,varchar,varchar)
returns integer as $$
declare
notify_assignee__task_id alias for $1;
notify_assignee__user_id alias for $2;
notify_assignee__callback alias for $3;
notify_assignee__custom_arg alias for $4;
notify_assignee__notification_type alias for $5;
v_deadline_pretty varchar;
v_object_name text;
v_workflow_key varchar;
v_transition_key wf_transitions.transition_key%TYPE;
v_transition_name wf_transitions.transition_name%TYPE;
v_party_from parties.party_id%TYPE;
v_party_to parties.party_id%TYPE;
v_subject text;
v_body text;
v_request_id integer;
v_workflow_url text;
v_acs_lang_package_id integer;
v_notifications_installed_p integer;
v_custom_arg varchar;
v_notification_type varchar;
v_notification_type_id integer;
v_workflow_package_id integer;
v_notification_n_seconds integer;
v_locale text;
v_str varchar;
v_user_first_names varchar;
v_user_last_name varchar;
begin
-- Default notification type
v_notification_type := notify_assignee__notification_type;
IF v_notification_type is null THEN
v_notification_type := 'wf_assignment_notif';
END IF;
-- Get information about the workflow context into variables
select to_char(ta.deadline,'Mon fmDDfm, YYYY HH24:MI:SS'),
acs_object__name(c.object_id), ta.workflow_key, tr.transition_key, tr.transition_name
into v_deadline_pretty, v_object_name, v_workflow_key, v_transition_key, v_transition_name
from wf_tasks ta, wf_transitions tr, wf_cases c
where ta.task_id = notify_assignee__task_id and
c.case_id = ta.case_id and
tr.workflow_key = c.workflow_key and
tr.transition_key = ta.transition_key;
select a.package_id, apm__get_value(p.package_id, 'SystemURL') || site_node__url(s.node_id)
into v_workflow_package_id, v_workflow_url
from site_nodes s, apm_packages a,
(select package_id
from apm_packages
where package_key = 'acs-kernel') p
where s.object_id = a.package_id and
a.package_key = 'acs-workflow';
v_workflow_url := v_workflow_url || 'task?task_id=' || notify_assignee__task_id;
select pe.first_names, pe.last_name
into v_user_first_names, v_user_last_name
from persons pe
where pe.person_id = notify_assignee__user_id;
RAISE NOTICE 'workflow_case__notify_assignee: task_id=%, user_id=%, obj=%, wf=%, trans=%',
notify_assignee__task_id, notify_assignee__user_id, v_object_name, v_workflow_key, v_transition_key;
select wfi.principal_party
into v_party_from
from wf_context_workflow_info wfi, wf_tasks ta, wf_cases c
where ta.task_id = notify_assignee__task_id and
c.case_id = ta.case_id and
wfi.workflow_key = c.workflow_key and
wfi.context_key = c.context_key;
if NOT FOUND then v_party_from := -1; end if;
-- Check whether the "notifications" package is installed and get
-- the notification interval of the user.
select count(*) into v_notifications_installed_p
from user_tab_columns
where lower(table_name) = 'notifications';
IF v_notifications_installed_p > 0 THEN
-- Notification Type is a kind of "channel" where to spread notifics
select type_id into v_notification_type_id
from notification_types
where short_name = v_notification_type;
-- Check if the user is "subscribed" to these notifications
select n_seconds into v_notification_n_seconds
from notification_requests r,
notification_intervals i
where r.interval_id = i.interval_id
and user_id = notify_assignee__user_id
and object_id = v_workflow_package_id
and type_id = v_notification_type_id;
-- Skip notification if there are no notifications defined
IF v_notification_n_seconds is null THEN return 0; END IF;
END IF;
-- Get the System Locale
select package_id into v_acs_lang_package_id
from apm_packages
where package_key = 'acs-lang';
v_locale := apm__get_value(v_acs_lang_package_id, 'SiteWideLocale');
-- make sure there are no null values - replaces(...,null) returns null...
IF v_deadline_pretty is NULL THEN v_deadline_pretty := 'undefined'; END IF;
IF v_workflow_url is NULL THEN v_workflow_url := 'undefined'; END IF;
-- ------------------------------------------------------------
-- Lookup message and substitute
v_subject := workflow_case__notify_l10n_lookup ('Notification_Subject', v_notification_type, v_workflow_key, v_transition_key, v_locale, 0);
v_subject := replace(v_subject, '%object_name%', v_object_name);
v_subject := replace(v_subject, '%transition_name%', v_transition_name);
v_subject := replace(v_subject, '%deadline%', v_deadline_pretty);
v_body := workflow_case__notify_l10n_lookup ('Notification_Body', v_notification_type, v_workflow_key, v_transition_key, v_locale, 1);
v_body := replace(v_body, '%deadline%', v_deadline_pretty);
v_body := replace(v_body, '%object_name%', v_object_name);
v_body := replace(v_body, '%transition_name%', v_transition_name);
v_body := replace(v_body, '%workflow_url%', v_workflow_url);
v_body := replace(v_body, '%first_names%', v_user_first_names);
v_body := replace(v_body, '%last_name%', v_user_first_names);
RAISE NOTICE 'workflow_case__notify_assignee: Subject=%, Body=%', v_subject, v_body;
v_custom_arg := notify_assignee__custom_arg;
IF v_custom_arg is null THEN v_custom_arg := 'null'; END IF;
if notify_assignee__callback != '' and notify_assignee__callback is not null then
v_str := 'select ' || notify_assignee__callback || ' (' ||
notify_assignee__task_id || ',' ||
quote_literal(v_custom_arg) || ',' ||
notify_assignee__user_id || ',' ||
v_party_from || ',' ||
quote_literal(v_subject) || ',' ||
quote_literal(v_body) || ')';
execute v_str;
else
v_request_id := acs_mail_nt__post_request (
v_party_from, -- party_from
notify_assignee__user_id, -- party_to
'f', -- expand_group
v_subject, -- subject
v_body, -- message
0 -- max_retries
);
end if;
return 0;
end;$$ language 'plpgsql';
-- procedure enable_transitions
create or replace function workflow_case__enable_transitions (integer)
returns integer as $$
declare
enable_transitions__case_id alias for $1;
v_task_id integer;
v_workflow_key varchar;
v_trigger_time timestamptz;
v_deadline_date timestamptz;
v_party_from integer;
v_subject varchar;
v_body text;
v_num_assigned integer;
trans_rec record;
begin
select workflow_key into v_workflow_key
from wf_cases
where case_id = enable_transitions__case_id;
/* we mark tasks overridden if they were once enabled, but are no longer so */
update wf_tasks
set state = 'overridden',
overridden_date = now()
where case_id = enable_transitions__case_id
and state = 'enabled'
and transition_key not in
(select transition_key
from wf_enabled_transitions
where case_id = enable_transitions__case_id);
/* insert a task for the transitions that are enabled but have no task row */
for trans_rec in select et.transition_key,
et.transition_name,
et.trigger_type,
et.enable_callback,
et.enable_custom_arg,
et.time_callback,
et.time_custom_arg,
et.deadline_callback,
et.deadline_custom_arg,
et.deadline_attribute_name,
et.notification_callback,
et.notification_custom_arg,
et.unassigned_callback,
et.unassigned_custom_arg,
et.estimated_minutes,
cr.assignment_callback,
cr.assignment_custom_arg
from wf_enabled_transitions et left outer join wf_context_role_info cr
on (et.workflow_key = cr.workflow_key and et.role_key = cr.role_key)
where et.case_id = enable_transitions__case_id
and not exists (select 1 from wf_tasks
where case_id = enable_transitions__case_id
and transition_key = et.transition_key
and state in ('enabled', 'started'))
LOOP
v_trigger_time := null;
v_deadline_date := null;
if trans_rec.trigger_type = 'user' then
v_deadline_date := workflow_case__get_task_deadline (
trans_rec.deadline_callback,
trans_rec.deadline_custom_arg,
trans_rec.deadline_attribute_name,
enable_transitions__case_id,
trans_rec.transition_key
);
end if;
v_trigger_time := workflow_case__execute_time_callback (
trans_rec.time_callback,
trans_rec.time_custom_arg,
enable_transitions__case_id,
trans_rec.transition_key);
/* we are ready to insert the row */
select nextval('t_wf_task_id_seq') into v_task_id from dual;
insert into wf_tasks (
task_id, case_id, workflow_key, transition_key,
deadline, trigger_time, estimated_minutes
) values (
v_task_id, enable_transitions__case_id, v_workflow_key,
trans_rec.transition_key,
v_deadline_date, v_trigger_time, trans_rec.estimated_minutes
);
PERFORM workflow_case__set_task_assignments (
v_task_id,
trans_rec.assignment_callback,
trans_rec.assignment_custom_arg
);
/* Execute the transition enabled callback */
PERFORM workflow_case__execute_transition_callback (
trans_rec.enable_callback,
trans_rec.enable_custom_arg,
enable_transitions__case_id,
trans_rec.transition_key
);
select count(*) into v_num_assigned
from wf_task_assignments
where task_id = v_task_id;
if v_num_assigned = 0 then
PERFORM workflow_case__execute_unassigned_callback (
trans_rec.unassigned_callback,
v_task_id,
trans_rec.unassigned_custom_arg
);
end if;
end loop;
return 0;
end;$$ language 'plpgsql';
-- procedure fire_transition_internal
create or replace function workflow_case__fire_transition_internal (integer,integer)
returns integer as $$
declare
fire_transition_internal__task_id alias for $1;
fire_transition_internal__journal_id alias for $2;
v_case_id integer;
v_state varchar;
v_transition_key varchar;
v_workflow_key varchar;
v_place_key varchar;
v_direction varchar;
v_guard_happy_p boolean;
v_fire_callback varchar;
v_fire_custom_arg text;
v_found_happy_guard boolean;
v_locked_task_id integer;
place_rec record;
begin
/* Select out some important variables */
select t.case_id, t.state, t.workflow_key, t.transition_key, ti.fire_callback, ti.fire_custom_arg
into v_case_id, v_state, v_workflow_key, v_transition_key, v_fire_callback, v_fire_custom_arg
from wf_tasks t, wf_cases c, wf_transition_info ti
where t.task_id = fire_transition_internal__task_id
and c.case_id = t.case_id
and ti.context_key = c.context_key
and ti.workflow_key = c.workflow_key
and ti.transition_key = t.transition_key;
/* Check that the state is either started or enabled */
if v_state = 'enabled' then
v_locked_task_id := null;
else if v_state = 'started' then
v_locked_task_id := fire_transition_internal__task_id;
else
raise EXCEPTION '-20000: Can not fire the transition if it is not in state enabled or started';
end if; end if;
/* Mark the task finished */
update wf_tasks
set state = 'finished',
finished_date = now()
where task_id = fire_transition_internal__task_id;
/* Consume the tokens */
FOR place_rec IN
select *
from wf_transition_places tp
where tp.workflow_key = v_workflow_key
and tp.transition_key = v_transition_key
LOOP
PERFORM workflow_case__consume_token (
v_case_id,
place_rec.place_key,
fire_transition_internal__journal_id,
v_locked_task_id
);
end loop;
/* Spit out new tokens in the output places */
v_found_happy_guard := 'f';
FOR place_rec IN
select *
from wf_transition_places tp
where tp.workflow_key = v_workflow_key
and tp.transition_key = v_transition_key
and direction = 'out'
LOOP
v_place_key := place_rec.place_key;
v_direction := place_rec.direction;
v_guard_happy_p := workflow_case__evaluate_guard (
place_rec.guard_callback,
place_rec.guard_custom_arg,
v_case_id,
v_workflow_key,
v_transition_key,
v_place_key,
v_direction
);
IF v_guard_happy_p = 't' THEN
v_found_happy_guard := 't';
PERFORM workflow_case__add_token (
v_case_id,
place_rec.place_key,
fire_transition_internal__journal_id
);
end if;
end loop;
/* If we did not find any happy guards, look for arcs with the special hash (#) guard */
if v_found_happy_guard = 'f' then
for place_rec in
select place_key
from wf_transition_places tp
where tp.workflow_key = v_workflow_key
and tp.transition_key = v_transition_key
and tp.direction = 'out'
and tp.guard_callback = '#'
loop
PERFORM workflow_case__add_token (
v_case_id,
place_rec.place_key,
fire_transition_internal__journal_id
);
end loop;
end if;
/* Execute the transition fire callback */
PERFORM workflow_case__execute_transition_callback (
v_fire_callback,
v_fire_custom_arg,
v_case_id,
v_transition_key
);
return 0;
end;$$ language 'plpgsql';
-- procedure ensure_task_in_state
create or replace function workflow_case__ensure_task_in_state (integer,varchar)
returns integer as $$
declare
ensure_task_in_state__task_id alias for $1;
ensure_task_in_state__state alias for $2;
v_count integer;
begin
select case when count(*) = 0 then 0 else 1 end into v_count
from wf_tasks
where task_id = ensure_task_in_state__task_id
and state = ensure_task_in_state__state;
if v_count != 1 then
raise EXCEPTION '-20000: The task % is not in state "%"', ensure_task_in_state__task_id, ensure_task_in_state__state;
end if;
return 0;
end;$$ language 'plpgsql';
-- procedure start_task
create or replace function workflow_case__start_task (integer,integer,integer)
returns integer as $$
declare
start_task__task_id alias for $1;
start_task__user_id alias for $2;
start_task__journal_id alias for $3;
v_case_id integer;
v_workflow_key wf_workflows.workflow_key%TYPE;
v_transition_key varchar(100);
v_hold_timeout_callback varchar(100);
v_hold_timeout_custom_arg varchar(4000);
v_hold_timeout timestamptz;
place_rec record;
begin
PERFORM workflow_case__ensure_task_in_state(start_task__task_id, 'enabled');
select t.case_id, t.workflow_key, t.transition_key, ti.hold_timeout_callback, ti.hold_timeout_custom_arg
into v_case_id, v_workflow_key, v_transition_key, v_hold_timeout_callback, v_hold_timeout_custom_arg
from wf_tasks t, wf_cases c, wf_transition_info ti
where t.task_id = start_task__task_id
and c.case_id = t.case_id
and ti.context_key = c.context_key
and ti.workflow_key = t.workflow_key
and ti.transition_key = t.transition_key;
v_hold_timeout := workflow_case__execute_hold_timeout_callback (
v_hold_timeout_callback,
v_hold_timeout_custom_arg,
v_case_id, v_transition_key
);
/* Mark it started */
update wf_tasks
set state = 'started',
started_date = now(),
holding_user = start_task__user_id,
hold_timeout = v_hold_timeout
where task_id = start_task__task_id;
/* Reserve one token from each input place */
for place_rec in select *
from wf_transition_places tp
where tp.workflow_key = v_workflow_key
and tp.transition_key = v_transition_key
and direction = 'in'
LOOP
PERFORM workflow_case__lock_token (
v_case_id,
place_rec.place_key,
start_task__journal_id,
start_task__task_id
);
end loop;
return 0;
end;$$ language 'plpgsql';
-- procedure cancel_task
create or replace function workflow_case__cancel_task (integer,integer)
returns integer as $$
declare
cancel_task__task_id alias for $1;
cancel_task__journal_id alias for $2;
v_case_id integer;
begin
PERFORM workflow_case__ensure_task_in_state (cancel_task__task_id,
'started');
select case_id into v_case_id
from wf_tasks
where task_id = cancel_task__task_id;
/* Mark the task canceled */
update wf_tasks
set state = 'canceled',
canceled_date = now()
where task_id = cancel_task__task_id;
/* Release our reserved tokens */
PERFORM workflow_case__release_token (
cancel_task__task_id,
cancel_task__journal_id
);
/* The workflow state has now changed, so we must run this */
PERFORM workflow_case__sweep_automatic_transitions (
v_case_id,
cancel_task__journal_id
);
return 0;
end;$$ language 'plpgsql';
-- procedure finish_task
create or replace function workflow_case__finish_task (integer,integer)
returns integer as $$
declare
finish_task__task_id alias for $1;
finish_task__journal_id alias for $2;
v_case_id integer;
begin
select case_id into v_case_id
from wf_tasks
where task_id = finish_task__task_id;
PERFORM workflow_case__fire_transition_internal (
finish_task__task_id,
finish_task__journal_id
);
PERFORM workflow_case__sweep_automatic_transitions (
v_case_id,
finish_task__journal_id
);
return 0;
end;$$ language 'plpgsql';
create or replace function workflow_case__get_task_id (integer, integer)
returns integer as $$
declare
get_task_id__case_id alias for $1;
get_task_id__transition_key alias for $2;
v_task_id integer;
begin
select task_id into v_task_id
from wf_tasks
where case_id = get_task_id__case_id and
transition_key = get_task_id__transition_key;
IF not found THEN
raise EXCEPTION 'Case % has no transition with key %', get_task_id__case_id, get_task_id__transition_key;
END IF;
return v_task_id;
end;$$ language 'plpgsql';
acs-workflow-master/sql/postgresql/workflow-case-package-head.sql 0000664 0000000 0000000 00000000000 14575002472 0025557 0 ustar 00root root 0000000 0000000 acs-workflow-master/sql/postgresql/workflow-case-package.sql 0000664 0000000 0000000 00000000464 14575002472 0024676 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/workflow-case-package.sql
--
-- Creates the PL/SQL package that provides the API for interacting
-- with a workflow case.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
\i workflow-case-package-head.sql
\i workflow-case-package-body.sql acs-workflow-master/sql/postgresql/workflow-package-body.sql 0000664 0000000 0000000 00000061100 14575002472 0024712 0 ustar 00root root 0000000 0000000 -- /packages/acs-workflow/sql/postgresql/workflow-package-body.sql
-- create or replace package body workflow
-- function create_workflow
create or replace function workflow__create_workflow (varchar,varchar,varchar,varchar,varchar,varchar)
returns varchar as $$
declare
create_workflow__workflow_key alias for $1;
create_workflow__pretty_name alias for $2;
create_workflow__pretty_plural alias for $3; -- default null
create_workflow__description alias for $4; -- default null
create_workflow__table_name alias for $5;
create_workflow__id_column alias for $6; -- default 'case_id'
v_num_rows integer;
v_workflow_key varchar;
begin
select count(*) into v_num_rows from pg_class
where relname = lower(create_workflow__table_name);
if v_num_rows = 0 then
raise EXCEPTION '-20000: The table "%"must be created before calling workflow.create_workflow.', create_workflow__table_name;
end if;
if substr(create_workflow__workflow_key, length(create_workflow__workflow_key) - 2, 3) != '_wf' then
v_workflow_key := create_workflow__workflow_key || '_wf';
else
v_workflow_key := create_workflow__workflow_key;
end if;
PERFORM acs_object_type__create_type (
v_workflow_key,
create_workflow__pretty_name,
create_workflow__pretty_plural,
'workflow',
create_workflow__table_name,
create_workflow__id_column,
null,
'f',
null,
null
);
insert into wf_workflows (
workflow_key, description
) values (
v_workflow_key, create_workflow__description
);
return v_workflow_key;
end;$$ language 'plpgsql';
/* Note: The workflow-specific cases table must be dropped before calling this proc */
create or replace function workflow__drop_workflow (varchar)
returns integer as $$
declare
drop_workflow__workflow_key alias for $1;
v_table_name varchar;
v_num_rows integer;
attribute_rec record;
begin
select table_name into v_table_name from acs_object_types
where object_type = drop_workflow__workflow_key;
select case when count(*) = 0 then 0 else 1 end into v_num_rows from pg_class
where relname = lower(v_table_name);
if v_num_rows > 0 then
raise EXCEPTION '-20000: The table "%" must be dropped before calling workflow__drop_workflow.', v_table_name;
end if;
select case when count(*) = 0 then 0 else 1 end into v_num_rows from wf_cases
where workflow_key = drop_workflow__workflow_key;
if v_num_rows > 0 then
raise EXCEPTION '-20000: You must delete all cases of workflow "%" before dropping the workflow definition.', drop_workflow__workflow_key;
end if;
/* Delete all the auxillary stuff */
delete from wf_context_task_panels where workflow_key = drop_workflow__workflow_key;
delete from wf_context_assignments where workflow_key = drop_workflow__workflow_key;
delete from wf_context_role_info where workflow_key = drop_workflow__workflow_key;
delete from wf_context_transition_info where workflow_key = drop_workflow__workflow_key;
delete from wf_context_workflow_info where workflow_key = drop_workflow__workflow_key;
delete from wf_arcs where workflow_key = drop_workflow__workflow_key;
delete from wf_places where workflow_key = drop_workflow__workflow_key;
delete from wf_transition_role_assign_map where workflow_key = drop_workflow__workflow_key;
delete from wf_transitions where workflow_key = drop_workflow__workflow_key;
delete from wf_roles where workflow_key = drop_workflow__workflow_key;
/* Drop all attributes */
for attribute_rec in
select attribute_id, attribute_name
from acs_attributes
where object_type = drop_workflow__workflow_key
LOOP
/* there is no on delete cascade, so we have to manually
* delete all the values
*/
delete from acs_attribute_values where attribute_id = attribute_rec.attribute_id;
PERFORM workflow__drop_attribute (
drop_workflow__workflow_key,
attribute_rec.attribute_name
);
end loop;
/* Delete the workflow */
delete from wf_workflows where workflow_key = drop_workflow__workflow_key;
PERFORM acs_object_type__drop_type (
drop_workflow__workflow_key,
'f'
);
return 0;
end;$$ language 'plpgsql';
-- procedure delete_cases
create or replace function workflow__delete_cases (varchar)
returns integer as $$
declare
delete_cases__workflow_key alias for $1;
case_rec record;
begin
for case_rec in
select case_id
from wf_cases
where workflow_key = delete_cases__workflow_key
LOOP
PERFORM workflow_case__delete(case_rec.case_id);
end loop;
return 0;
end;$$ language 'plpgsql';
-- function create_attribute
create or replace function workflow__create_attribute (varchar,varchar,varchar,varchar,varchar,varchar,varchar,varchar,integer,integer,integer,varchar)
returns integer as $$
declare
create_attribute__workflow_key alias for $1;
create_attribute__attribute_name alias for $2;
create_attribute__datatype alias for $3;
create_attribute__pretty_name alias for $4;
create_attribute__pretty_plural alias for $5; -- default null
create_attribute__table_name alias for $6; -- default null
create_attribute__column_name alias for $7; -- default null
create_attribute__default_value alias for $8; -- default null
create_attribute__min_n_values alias for $9; -- default 1
create_attribute__max_n_values alias for $10; -- default 1
create_attribute__sort_order alias for $11; -- default null
create_attribute__storage alias for $12; -- default 'generic'
v_attribute_id integer;
begin
v_attribute_id := acs_attribute__create_attribute(
create_attribute__workflow_key,
create_attribute__attribute_name,
create_attribute__datatype,
create_attribute__pretty_name,
create_attribute__pretty_plural,
create_attribute__table_name,
create_attribute__column_name,
create_attribute__default_value,
create_attribute__min_n_values,
create_attribute__max_n_values,
create_attribute__sort_order,
create_attribute__storage,
'f'
);
return v_attribute_id;
end;$$ language 'plpgsql';
-- procedure drop_attribute
create or replace function workflow__drop_attribute (varchar,varchar)
returns integer as $$
declare
drop_attribute__workflow_key alias for $1;
drop_attribute__attribute_name alias for $2;
v_attribute_id integer;
begin
select attribute_id into v_attribute_id
from acs_attributes
where object_type = drop_attribute__workflow_key
and attribute_name = drop_attribute__attribute_name;
PERFORM acs_attribute__drop_attribute (
drop_attribute__workflow_key,
drop_attribute__attribute_name
);
return 0;
end;$$ language 'plpgsql';
-- procedure add_place
create or replace function workflow__add_place (varchar,varchar,varchar,integer)
returns integer as $$
declare
add_place__workflow_key alias for $1;
add_place__place_key alias for $2;
add_place__place_name alias for $3;
add_place__sort_order alias for $4;
v_sort_order integer;
begin
if add_place__sort_order is null then
select coalesce(max(sort_order)+1, 1)
into v_sort_order
from wf_places
where workflow_key = add_place__workflow_key;
else
v_sort_order := add_place__sort_order;
end if;
insert into wf_places (workflow_key, place_key, place_name, sort_order)
values (add_place__workflow_key, add_place__place_key,add_place__place_name, add_place__sort_order);
return 0;
end;$$ language 'plpgsql';
-- procedure delete_place
create or replace function workflow__delete_place (varchar,varchar)
returns integer as $$
declare
delete_place__workflow_key alias for $1;
delete_place__place_key alias for $2;
begin
delete from wf_places
where workflow_key = delete_place__workflow_key
and place_key = delete_place__place_key;
return 0;
end;$$ language 'plpgsql';
-- procedure add_role
create or replace function workflow__add_role (varchar,varchar,varchar,integer)
returns integer as $$
declare
add_role__workflow_key alias for $1;
add_role__role_key alias for $2;
add_role__role_name alias for $3;
add_role__sort_order alias for $4;
v_sort_order integer;
begin
if add_role__sort_order is null then
select coalesce(max(sort_order)+1, 1)
into v_sort_order
from wf_roles
where workflow_key = add_role__workflow_key;
else
v_sort_order := add_role__sort_order;
end if;
insert into wf_roles (
workflow_key, role_key, role_name, sort_order
) values (
add_role__workflow_key, add_role__role_key, add_role__role_name, v_sort_order
);
return 0;
end;$$ language 'plpgsql';
-- procedure move_role_up
create or replace function workflow__move_role_up (varchar,varchar)
returns integer as $$
declare
move_role_up__workflow_key alias for $1;
move_role_up__role_key alias for $2;
v_this_sort_order integer;
v_prior_sort_order integer;
begin
select sort_order into v_this_sort_order
from wf_roles
where workflow_key = move_role_up__workflow_key
and role_key = move_role_up__role_key;
select max(sort_order) into v_prior_sort_order
from wf_roles
where workflow_key = move_role_up__workflow_key
and sort_order < v_this_sort_order;
if not found then
/* already at top of sort order */
return 0;
end if;
/* switch the sort orders around */
update wf_roles
set sort_order = (case when role_key=move_role_up__role_key then v_prior_sort_order else v_this_sort_order end)
where workflow_key = move_role_up__workflow_key
and sort_order in (v_this_sort_order, v_prior_sort_order);
return 0;
end;$$ language 'plpgsql';
-- procedure move_role_down
create or replace function workflow__move_role_down (varchar,varchar)
returns integer as $$
declare
move_role_down__workflow_key alias for $1;
move_role_down__role_key alias for $2;
v_this_sort_order integer;
v_next_sort_order integer;
begin
select sort_order
into v_this_sort_order
from wf_roles
where workflow_key = move_role_down__workflow_key
and role_key = move_role_down__role_key;
select min(sort_order)
into v_next_sort_order
from wf_roles
where workflow_key = move_role_down__workflow_key
and sort_order > v_this_sort_order;
if not found then
/* already at bottom of sort order */
return 0;
end if;
/* switch the sort orders around */
update wf_roles
set sort_order = (case when role_key=move_role_down__role_key then v_next_sort_order else v_this_sort_order end)
where workflow_key = move_role_down__workflow_key
and sort_order in (v_this_sort_order, v_next_sort_order);
return 0;
end;$$ language 'plpgsql';
-- procedure delete_role
create or replace function workflow__delete_role (varchar,varchar)
returns integer as $$
declare
delete_role__workflow_key alias for $1;
delete_role__role_key alias for $2;
begin
/* First, remove all references to this role from transitions */
update wf_transitions
set role_key = null
where workflow_key = delete_role__workflow_key
and role_key = delete_role__role_key;
delete from wf_roles
where workflow_key = delete_role__workflow_key
and role_key = delete_role__role_key;
return 0;
end;$$ language 'plpgsql';
-- procedure add_transition
create or replace function workflow__add_transition (varchar,varchar,varchar,varchar,integer,varchar)
returns integer as $$
declare
add_transition__workflow_key alias for $1;
add_transition__transition_key alias for $2;
add_transition__transition_name alias for $3;
add_transition__role_key alias for $4;
add_transition__sort_order alias for $5;
add_transition__trigger_type alias for $6; -- default 'user'
v_sort_order integer;
begin
if add_transition__sort_order is null then
select coalesce(max(sort_order)+1, 1)
into v_sort_order
from wf_transitions
where workflow_key = add_transition__workflow_key;
else
v_sort_order := add_transition__sort_order;
end if;
insert into wf_transitions (
workflow_key,
transition_key,
transition_name,
role_key,
sort_order,
trigger_type
) values (
add_transition__workflow_key,
add_transition__transition_key,
add_transition__transition_name,
add_transition__role_key,
v_sort_order,
add_transition__trigger_type
);
return 0;
end;$$ language 'plpgsql';
-- procedure delete_transition
create or replace function workflow__delete_transition (varchar,varchar)
returns integer as $$
declare
delete_transition__workflow_key alias for $1;
delete_transition__transition_key alias for $2;
begin
delete from wf_transitions
where workflow_key = delete_transition__workflow_key
and transition_key = delete_transition__transition_key;
return 0;
end;$$ language 'plpgsql';
-- procedure add_arc
create or replace function workflow__add_arc (varchar,varchar,varchar,varchar,varchar,varchar,varchar)
returns integer as $$
declare
add_arc__workflow_key alias for $1;
add_arc__transition_key alias for $2;
add_arc__place_key alias for $3;
add_arc__direction alias for $4;
add_arc__guard_callback alias for $5; -- default null
add_arc__guard_custom_arg alias for $6; -- default null
add_arc__guard_description alias for $7; -- default null
begin
insert into wf_arcs (workflow_key, transition_key, place_key, direction,
guard_callback, guard_custom_arg, guard_description)
values (add_arc__workflow_key, add_arc__transition_key, add_arc__place_key, add_arc__direction,
add_arc__guard_callback, add_arc__guard_custom_arg, add_arc__guard_description);
return 0;
end;$$ language 'plpgsql';
-- procedure add_arc
create or replace function workflow__add_arc (varchar,varchar,varchar,varchar,varchar,varchar)
returns integer as $$
declare
add_arc__workflow_key alias for $1;
add_arc__from_transition_key alias for $2;
add_arc__to_place_key alias for $3;
add_arc__guard_callback alias for $4;
add_arc__guard_custom_arg alias for $5;
add_arc__guard_description alias for $6;
begin
perform workflow__add_arc (
add_arc__workflow_key,
add_arc__from_transition_key,
add_arc__to_place_key,
'out',
add_arc__guard_callback,
add_arc__guard_custom_arg,
add_arc__guard_description
);
return 0;
end;$$ language 'plpgsql';
-- procedure add_arc
create or replace function workflow__add_arc (varchar,varchar,varchar)
returns integer as $$
declare
add_arc__workflow_key alias for $1;
add_arc__from_place_key alias for $2;
add_arc__to_transition_key alias for $3;
begin
perform workflow__add_arc(
add_arc__workflow_key,
add_arc__to_transition_key,
add_arc__from_place_key,
'in',
null,
null,
null
);
return 0;
end;$$ language 'plpgsql';
-- procedure delete_arc
create or replace function workflow__delete_arc (varchar,varchar,varchar,varchar)
returns integer as $$
declare
delete_arc__workflow_key alias for $1;
delete_arc__transition_key alias for $2;
delete_arc__place_key alias for $3;
delete_arc__direction alias for $4;
begin
delete from wf_arcs
where workflow_key = delete_arc__workflow_key
and transition_key = delete_arc__transition_key
and place_key = delete_arc__place_key
and direction = delete_arc__direction;
return 0;
end;$$ language 'plpgsql';
-- procedure add_trans_attribute_map
create or replace function workflow__add_trans_attribute_map (varchar,varchar,integer,integer)
returns integer as $$
declare
p_workflow_key alias for $1;
p_transition_key alias for $2;
p_attribute_id alias for $3;
p_sort_order alias for $4;
v_num_rows integer;
v_sort_order integer;
begin
select count(*)
into v_num_rows
from wf_transition_attribute_map
where workflow_key = p_workflow_key
and transition_key = p_transition_key
and attribute_id = p_attribute_id;
if v_num_rows > 0 then
return 0;
end if;
if p_sort_order is null then
select coalesce(max(sort_order)+1, 1)
into v_sort_order
from wf_transition_attribute_map
where workflow_key = p_workflow_key
and transition_key = p_transition_key;
else
v_sort_order := p_sort_order;
end if;
insert into wf_transition_attribute_map (
workflow_key,
transition_key,
attribute_id,
sort_order
) values (
p_workflow_key,
p_transition_key,
p_attribute_id,
v_sort_order
);
return 0;
end;$$ language 'plpgsql';
-- procedure add_trans_attribute_map
create or replace function workflow__add_trans_attribute_map (varchar,varchar,varchar,integer)
returns integer as $$
declare
p_workflow_key alias for $1;
p_transition_key alias for $2;
p_attribute_name alias for $3;
p_sort_order alias for $4;
v_attribute_id integer;
begin
select attribute_id
into v_attribute_id
from acs_attributes
where object_type = p_workflow_key
and attribute_name = p_attribute_name;
perform workflow__add_trans_attribute_map (
p_workflow_key,
p_transition_key,
v_attribute_id,
p_sort_order
);
return 0;
end;$$ language 'plpgsql';
-- procedure delete_trans_attribute_map
create or replace function workflow__delete_trans_attribute_map (varchar,varchar,integer)
returns integer as $$
declare
p_workflow_key alias for $1;
p_transition_key alias for $2;
p_attribute_id alias for $3;
begin
delete
from wf_transition_attribute_map
where workflow_key = p_workflow_key
and transition_key = p_transition_key
and attribute_id = p_attribute_id;
return 0;
end;$$ language 'plpgsql';
-- procedure delete_trans_attribute_map
create or replace function workflow__delete_trans_attribute_map (varchar,varchar,varchar)
returns integer as $$
declare
p_workflow_key alias for $1;
p_transition_key alias for $2;
p_attribute_name alias for $3;
v_attribute_id integer;
begin
select attribute_id
into v_attribute_id
from acs_attributes
where object_type = p_workflow_key
and attribute_name = p_attribute_name;
delete from wf_transition_attribute_map
where workflow_key = p_workflow_key
and transition_key = p_transition_key
and attribute_id = v_attribute_id;
return 0;
end;$$ language 'plpgsql';
-- procedure add_trans_role_assign_map
create or replace function workflow__add_trans_role_assign_map (varchar,varchar,varchar)
returns integer as $$
declare
p_workflow_key alias for $1;
p_transition_key alias for $2;
p_assign_role_key alias for $3;
v_num_rows integer;
begin
select count(*)
into v_num_rows
from wf_transition_role_assign_map
where workflow_key = p_workflow_key
and transition_key = p_transition_key
and assign_role_key = p_assign_role_key;
if v_num_rows = 0 then
insert into wf_transition_role_assign_map (
workflow_key,
transition_key,
assign_role_key
) values (
p_workflow_key,
p_transition_key,
p_assign_role_key
);
end if;
return 0;
end;$$ language 'plpgsql';
-- procedure delete_trans_role_assign_map
create or replace function workflow__delete_trans_role_assign_map (varchar,varchar,varchar)
returns integer as $$
declare
p_workflow_key alias for $1;
p_transition_key alias for $2;
p_assign_role_key alias for $3;
begin
delete from wf_transition_role_assign_map
where workflow_key = p_workflow_key
and transition_key = p_transition_key
and assign_role_key = p_assign_role_key;
return 0;
end;$$ language 'plpgsql';
create sequence workflow_session_id;
create table previous_place_list (
session_id integer,
rcnt integer,
constraint previous_place_list_pk
primary key (session_id, rcnt),
ky varchar(100)
);
create table target_place_list (
session_id integer,
rcnt integer,
constraint target_place_list_pk
primary key (session_id, rcnt),
ky varchar(100)
);
create table guard_list (
session_id integer,
rcnt integer,
constraint quard_list_pk
primary key (session_id, rcnt),
ky varchar(100)
);
create or replace function workflow__simple_p (varchar)
returns boolean as $$
declare
simple_p__workflow_key alias for $1;
v_session_id integer;
retval boolean;
begin
v_session_id := nextval('workflow_session_id');
retval := __workflow__simple_p(simple_p__workflow_key, v_session_id);
delete from previous_place_list where session_id = v_session_id;
delete from target_place_list where session_id = v_session_id;
delete from guard_list where session_id = v_session_id;
return retval;
end;$$ language 'plpgsql';
-- function simple_p
create or replace function __workflow__simple_p (varchar,integer)
returns boolean as $$
declare
simple_p__workflow_key alias for $1;
v_session_id alias for $2;
-- previous_place_list t_place_table;
-- target_place_list t_place_table;
-- guard_list t_guard_table;
guard_list_1 varchar;
guard_list_2 varchar;
target_place_list_1 varchar;
target_place_list_2 varchar;
previous_place_list_i varchar;
v_row_count integer default 0;
v_count integer;
v_count2 integer;
v_place_key wf_places.place_key%TYPE;
v_end_place wf_places.place_key%TYPE;
v_transition_key wf_transitions.transition_key%TYPE;
v_rownum integer;
v_target record;
begin
/* Let us do some simple checks first */
/* Places with more than one arc out */
select count(*) into v_count
from wf_places p
where p.workflow_key = simple_p__workflow_key
and 1 < (select count(*)
from wf_arcs a
where a.workflow_key = p.workflow_key
and a.place_key = p.place_key
and direction = 'in');
raise notice 'query 1';
if v_count > 0 then
return 'f';
end if;
/* Transitions with more than one arc in */
select count(*) into v_count
from wf_transitions t
where t.workflow_key = simple_p__workflow_key
and 1 < (select count(*)
from wf_arcs a
where a.workflow_key = t.workflow_key
and a.transition_key = t.transition_key
and direction = 'in');
raise notice 'query 2';
if v_count > 0 then
return 'f';
end if;
/* Transitions with more than two arcs out */
select count(*) into v_count
from wf_transitions t
where t.workflow_key = simple_p__workflow_key
and 2 < (select count(*)
from wf_arcs a
where a.workflow_key = t.workflow_key
and a.transition_key = t.transition_key
and direction = 'out');
raise notice 'query 3';
if v_count > 0 then
return 'f';
end if;
/* Now we do the more complicated checks.
* We keep a list of visited places because I could not think
* of a nicer way that was not susceptable to infinite loops.
*/
v_place_key := 'start';
v_end_place := 'end';
loop
exit when v_place_key = v_end_place;
-- previous_place_list(v_row_count) := v_place_key;
insert into previous_place_list
(session_id,rcnt,ky)
values
(v_session_id,v_row_count,v_place_key);
raise notice 'query 4';
select distinct transition_key into v_transition_key
from wf_arcs
where workflow_key = simple_p__workflow_key
and place_key = v_place_key
and direction = 'in';
raise notice 'query 5';
select count(*) into v_count
from wf_arcs
where workflow_key = simple_p__workflow_key
and transition_key = v_transition_key
and direction = 'out';
raise notice 'query 6';
if v_count = 1 then
select distinct place_key into v_place_key
from wf_arcs
where workflow_key = simple_p__workflow_key
and transition_key = v_transition_key
and direction = 'out';
raise notice 'query 7';
else if v_count = 0 then
/* deadend! */
return 'f';
else
/* better be two based on our earlier test */
v_rownum := 1;
for v_target in
select place_key,guard_callback
from wf_arcs
where workflow_key = simple_p__workflow_key
and transition_key = v_transition_key
and direction = 'out'
LOOP
-- target_place_list(v_target.rownum) := v_target.place_key;
raise notice 'query 8';
insert into target_place_list (session_id,rcnt,ky)
values (v_session_id,v_rownum,v_target.place_key);
raise notice 'query 9';
-- guard_list(v_target.rownum) := v_target.guard_callback;
insert into guard_list (session_id,rcnt,ky)
values (v_session_id,v_rownum,v_target.guard_callback);
v_rownum := v_rownum + 1;
raise notice 'query 10';
end loop;
/* Check that the guard functions are the negation of each other
* by looking for the magic entry "#" (exactly once)
*/
select ky into guard_list_1 from guard_list
where session_id = v_session_id and rcnt = 1;
raise notice 'query 11';
select ky into guard_list_2 from guard_list
where session_id = v_session_id and rcnt = 2;
raise notice 'query 12';
if ((guard_list_1 != '#' and guard_list_2 != '#') or
(guard_list_1 = '#' and guard_list_2 = '#')) then
return 'f';
end if;
/* Check that exactly one of the targets is in the previous list */
v_count2 := 0;
select ky into target_place_list_1 from target_place_list
where session_id = v_session_id and rcnt = 1;
raise notice 'query 13';
select ky into target_place_list_2 from target_place_list
where session_id = v_session_id and rcnt = 2;
raise notice 'query 14';
for i in 0..v_row_count LOOP
select ky into previous_place_list_i
from previous_place_list where session_id = v_session_id
and rcnt = i;
if target_place_list_1 = previous_place_list_i then
v_count2 := v_count2 + 1;
v_place_key := target_place_list_2;
end if;
if target_place_list_2 = previous_place_list_i then
v_count2 := v_count2 + 1;
v_place_key := target_place_list_1;
end if;
end loop;
raise notice 'query 15';
if v_count2 != 1 then
return 'f';
end if;
end if; end if;
v_row_count := v_row_count + 1;
end loop;
/* if we got here, it must be okay */
return 't';
end;$$ language 'plpgsql';
acs-workflow-master/sql/postgresql/workflow-package-head.sql 0000664 0000000 0000000 00000000000 14575002472 0024646 0 ustar 00root root 0000000 0000000 acs-workflow-master/sql/postgresql/workflow-package.sql 0000664 0000000 0000000 00000000454 14575002472 0023764 0 ustar 00root root 0000000 0000000 --
-- acs-workflow/sql/workflow-package.sql
--
-- Creates the PL/SQL package that provides the API for defining and dropping
-- workflow cases.
--
-- @author Lars Pind (lars@pinds.com)
--
-- @creation-date 2000-05-18
--
-- @cvs-id $Id$
--
\i workflow-package-head.sql
\i workflow-package-body.sql
acs-workflow-master/tcl/ 0000775 0000000 0000000 00000000000 14575002472 0015555 5 ustar 00root root 0000000 0000000 acs-workflow-master/tcl/display-procs-oracle.xql 0000664 0000000 0000000 00000002313 14575002472 0022336 0 ustar 00root root 0000000 0000000
oracle8.1.6
select p.party_id,
acs_object.name(p.party_id) as name,
case when p.email = '' then '' else '('||p.email||' end') as email
from parties p
where 0 < (select count(*)
from users u,
party_approved_member_map m
where m.party_id = p.party_id
and u.user_id = m.member_id)
select p.party_id,
acs_object.name(p.party_id) as name,
case when p.email = '' then '' else '('||p.email||' end') as email
from parties p
where 0 < (select count(*)
from users u,
party_approved_member_map m
where m.party_id = p.party_id
and u.user_id = m.member_id)
acs-workflow-master/tcl/display-procs-postgresql.xql 0000664 0000000 0000000 00000002141 14575002472 0023273 0 ustar 00root root 0000000 0000000
postgresql7.1
select p.party_id,
acs_object__name(p.party_id) as name,
case when p.email = '' then '' else '('||p.email||')' end as email
from parties p
where 0 < (select count(*)
from users u,
party_approved_member_map m
where m.party_id = p.party_id
and u.user_id = m.member_id)
select p.party_id,
acs_object__name(p.party_id) as name,
case when p.email = '' then '' else '('||p.email||')' end as email
from parties p,
acs_objects o
where
p.party_id = o.object_id and
o.object_type in ('im_profile', 'user', 'person') and
0 < (
select count(*)
from users u,
party_approved_member_map m
where m.party_id = p.party_id
and u.user_id = m.member_id
)
order by
o.object_type, name
acs-workflow-master/tcl/display-procs.tcl 0000664 0000000 0000000 00000010470 14575002472 0021054 0 ustar 00root root 0000000 0000000 ad_library {
Procs to render workflow information in HTML.
@author Lars Pind (lars@pinds.com)
@creation-date 18 July 2000
@cvs-id $Id$
}
ad_proc wf_if_null { string value_if_null } {
If string is emtpy, returns value_if_null, otherwise returns string.
@author Lars Pind
@creation-date 27 September 2000
} {
if { [empty_string_p $string] } {
return $value_if_null
} else {
return $string
}
}
ad_proc wf_attribute_widget {
{-name ""}
attribute_info
} {
Returns an HTML fragment containing a form element for entering the value of an attribute.
This problem should eventually be solved completely by the templating subsystem.
@author Lars Pind (lars@pinds.com)
@creation-date 10 July, 2000
} {
array set attribute $attribute_info
if { [empty_string_p $name] } {
set name "attributes.$attribute(attribute_name)"
}
# The default widget
set widget ""
switch $attribute(datatype) {
boolean {
#set widget ""
set widget ""
}
number {
switch $attribute(wf_datatype) {
party {
set widget ""
}
}
}
}
return $widget
}
ad_proc wf_attribute_value_pretty {
attribute_info
} {
Returns a nice display version of the value of an attribute.
Specifically, it displays booleans as "#acs-kernel.common_Yes#" or "#acs-kernel.common_No#", and it
displays a party with the ad_present_user
function.
This is a kludge until the general ACS templating effort settles down.
@author Lars Pind (lars@pinds.com)
@creation-date 10 July, 2000
} {
array set attribute $attribute_info
set value $attribute(value)
switch $attribute(datatype) {
boolean {
set value [ad_decode $value "t" "#acs-kernel.common_Yes#" "#acs-kernel.common_No#"]
}
}
return $value
}
ad_proc wf_assignment_widget {
{-name ""}
-case_id
role_key
} {
Returns an HTML fragment containing a form element for entering the value of an attribute.
This problem should eventually be solved completely by the templating subsystem.
@author Lars Pind (lars@pinds.com)
@creation-date 10 July, 2000
} {
if { [empty_string_p $name] } {
set name "assignments.$role_key"
}
if { [info exists case_id] && ![empty_string_p $case_id] } {
set current_assignments [db_list assignment_select "
select ca.party_id
from wf_case_assignments ca,
wf_cases c
where c.case_id = :case_id
and ca.role_key = :role_key
and ca.workflow_key = c.workflow_key
order by party_id
"]
} else {
set current_assignments {}
}
set widget ""
return $widget
}
acs-workflow-master/tcl/display-procs.xql 0000664 0000000 0000000 00000000545 14575002472 0021100 0 ustar 00root root 0000000 0000000
select ca.party_id
from wf_case_assignments ca, wf_cases c
where c.case_id = :case_id
and ca.role_key = :role_key
and ca.workflow_key = c.workflow_key
acs-workflow-master/tcl/expenses-procs.tcl 0000664 0000000 0000000 00000000467 14575002472 0021246 0 ustar 00root root 0000000 0000000 ad_proc wf_expenses_get_assign_panels {
-task_info:required
} {
array set task $task_info
lappend panels [list title "Input" body "$task(object_type_pretty): $task(object_name)"]
lappend panels [list title "Logic and Aids" body "Here are some logics and aids."]
return $panels
}
acs-workflow-master/tcl/graph-init.tcl 0000664 0000000 0000000 00000000217 14575002472 0020323 0 ustar 00root root 0000000 0000000
ns_cache create workflow_info -timeout 60
# Initialize a "semaphore" to 0 to protect the "dot" GraphWiz.
nsv_set acs_workflow dot_busy_p 0
acs-workflow-master/tcl/graph-procs.tcl 0000664 0000000 0000000 00000041142 14575002472 0020510 0 ustar 00root root 0000000 0000000 ad_library {
Helper procs for generating graphical representations of workflows.
@author Lars Pind (lars@pinds.com)
@creation-date September 15, 2000
@cvs-id $Id$
}
ad_proc wf_get_workflow_net_internal {
workflow_key
} {
set workflow(transitions) {}
set workflow(places) {}
set workflow(arcs) {}
set workflow(pretty_name) [db_string workflow_name \
{ select pretty_name from acs_object_types where object_type = :workflow_key }]
set workflow(workflow_key) $workflow_key
db_foreach transition_def {
select transition_key,
transition_name,
sort_order,
trigger_type
from wf_transitions
where workflow_key = :workflow_key
order by sort_order
} {
lappend workflow(transitions) $transition_key
set workflow(transition,$transition_key,transition_key) $transition_key
set workflow(transition,$transition_key,transition_name) $transition_name
set workflow(transition,$transition_key,sort_order) $sort_order
set workflow(transition,$transition_key,trigger_type) $trigger_type
set workflow(arcs,transition,$transition_key,in) [list]
set workflow(arcs,transition,$transition_key,out) [list]
}
db_foreach places_def {
select p.place_key,
p.place_name,
p.sort_order
from wf_places p
where p.workflow_key = :workflow_key
order by p.sort_order
} {
lappend workflow(places) $place_key
set workflow(place,$place_key,place_key) $place_key
set workflow(place,$place_key,place_name) $place_name
set workflow(place,$place_key,sort_order) $sort_order
set workflow(arcs,place,$place_key,in) [list]
set workflow(arcs,place,$place_key,out) [list]
}
db_foreach arcs_def {
select transition_key,
place_key,
direction,
guard_callback,
guard_custom_arg,
guard_description
from wf_arcs
where workflow_key = :workflow_key
} {
# lets you say workflow(arc,$arc), where $arc is an element from this list.
lappend workflow(arcs) "$transition_key,$place_key,$direction"
# makes it possible to easily get the input/output places for a given transition
lappend workflow(arcs,transition,$transition_key,$direction) $place_key
# ... and for a given place
lappend workflow(arcs,place,$place_key,$direction) $transition_key
set workflow(arc,$transition_key,$place_key,$direction,guard_callback) $guard_callback
set workflow(arc,$transition_key,$place_key,$direction,guard_custom_arg) $guard_custom_arg
set workflow(arc,$transition_key,$place_key,$direction,guard_description) $guard_description
# makes it easier to know what direction to draw the arrow in
set workflow(arc,$transition_key,$place_key,$direction,from) \
[ad_decode $direction "in" "place,$place_key" "transition,$transition_key"]
set workflow(arc,$transition_key,$place_key,$direction,to) \
[ad_decode $direction "in" "transition,$transition_key" "place,$place_key"]
}
return [array get workflow]
}
ad_proc wf_get_workflow_net {
workflow_key
} {
We cache the workflow net, although we don't really need that anymore.
} {
return [ns_cache eval workflow_info $workflow_key {wf_get_workflow_net_internal $workflow_key}]
}
ad_proc wf_workflow_changed {
workflow_key
} {
Flushes the cache.
} {
ns_cache flush workflow_info $workflow_key
}
ad_proc wf_decorate_workflow {
{-mode "normal"}
{-format "graph"}
{-selected_transition_key ""}
{-selected_place_key ""}
{-return_url ""}
workflow_varname
} {
Adds linking information to the workflow net, based on the arguments given.
} {
upvar 1 $workflow_varname workflow
# ad_return_complaint xx [array get workflow]
# foreach {key value} [array get workflow] {
# ds_comment "key: $key, value: $value"
# }
#####
#
# Establish links for the graph
#
#####
set place_link {}
set transition_link {}
set nolink [list]
set onlylink [list]
switch $mode {
normal {
# set transition_key $workflow(transition,$transition_key,transition_key)
set transition_link "define?[export_vars -url { format mode transition_key}]&"
set place_link "define?[export_vars -url { format mode}]&"
}
arcadd {
if { ![empty_string_p $selected_place_key] } {
set direction in
set place_link {}
set transition_link "[export_vars -base "arc-add" { {place_key $selected_place_key} direction return_url}]&"
foreach loop_transition_key $workflow(arcs,place,$selected_place_key,in) {
lappend nolink "transition,$loop_transition_key"
}
} else {
set direction out
set transition_link {}
set place_link "[export_vars -base "arc-add" { {transition_key $selected_transition_key} direction return_url}]&"
foreach loop_place_key $workflow(arcs,transition,$selected_transition_key,out) {
lappend nolink "place,$loop_place_key"
}
}
}
arcdelete {
if { ![empty_string_p $selected_place_key] } {
set direction in
set place_link {}
set transition_link "[export_vars -base "arc-delete" { {place_key $selected_place_key} direction return_url}]&"
foreach loop_transition_key $workflow(arcs,place,$selected_place_key,in) {
lappend onlylink "transition,$loop_transition_key"
}
} else {
set direction out
set transition_link {}
set place_link "[export_vars -base "arc-delete" { {transition_key $selected_transition_key} direction return_url}]&"
foreach loop_place_key $workflow(arcs,transition,$selected_transition_key,out) {
lappend onlylink "place,$loop_place_key"
}
}
}
}
if { [empty_string_p $onlylink] && [empty_string_p $nolink] && \
![empty_string_p $transition_link] && ![empty_string_p $place_link] } {
set arc_color black
} else {
set arc_color grey
}
set workflow(place_link) $place_link
set workflow(transition_link) $transition_link
set workflow(nolink) $nolink
set workflow(onlylink) $onlylink
set workflow(selected_transition_key) $selected_transition_key
set workflow(selected_place_key) $selected_place_key
set workflow(arc_color) $arc_color
#####
#
# Translate this into the representation
# (this is the same for both HTML and graphical representation)
#
#####
# to make export_vars easier
set workflow_key $workflow(workflow_key)
foreach type { transition place } {
foreach key $workflow(${type}s) {
if { [empty_string_p $onlylink] } {
eval "set ${type}_key [ns_urlencode $key]"
set par [list]
lappend par workflow_key "${type}_key"
set workflow($type,$key,url) [ad_decode \
[set ${type}_link] \
"" "" \
"[set ${type}_link][export_vars -url $par]"]
} else {
set workflow($type,$key,url) {}
}
}
}
foreach key $onlylink {
set type [lindex [split $key ","] 0]
set type_key [lindex [split $key ","] 1]
set workflow($key,url) [ad_decode \
[set ${type}_link] \
"" "" \
"[set ${type}_link][export_vars -url { workflow_key ${type}_key=[ns_urlencode ${type_key}]}]"]
}
foreach key $nolink {
set workflow($key,url) {}
}
}
ad_proc wf_generate_dot_representation {
{-orientation portrait}
{-rankdir UD}
{-size}
{-debug 0 }
workflow_varname
} {
Generates a dot-file for use with Graphviz.
From such a dot-file, we can generate both a GIF image and an imagemap.
@param Tcl representation of a workflow net, as returned by wf_get_workflow_net.
@author Lars Pind (lars@pinds.com)
@creation-date 28 September 2000
} {
upvar 1 $workflow_varname workflow
set package_id [db_string package_id {select package_id from apm_packages where package_key='acs-workflow'}]
set transition_font_name [im_parameter -package_id $package_id "transition_font_name"]
set place_font_name [im_parameter -package_id $package_id "place_font_name"]
set guard_font_name [im_parameter -package_id $package_id "guard_font_name"]
set transition_font_size [im_parameter -package_id $package_id "transition_font_size"]
set place_font_size [im_parameter -package_id $package_id "place_font_size"]
set guard_font_size [im_parameter -package_id $package_id "guard_font_size"]
# Add graph-specific info to the data structure
foreach type { transition place } {
foreach key $workflow(${type}s) {
set workflow($type,$key,style) solid
set workflow($type,$key,shape) [ad_decode $type "transition" "box" "circle"]
set workflow($type,$key,label) [ad_decode $type "transition" $workflow($type,$key,${type}_name) ""]
set workflow($type,$key,peripheries) 1
set workflow($type,$key,fontname) [ad_decode $type "transition" $transition_font_name $place_font_name]
set workflow($type,$key,fontsize) [ad_decode $type "transition" $transition_font_size $place_font_size]
set workflow($type,$key,height) [ad_decode $type "transition" 0.4 0.2]
set workflow($type,$key,width) [ad_decode $type "transition" 0.4 0.2]
set workflow($type,$key,URL) $workflow($type,$key,url)
if { ![empty_string_p $workflow($type,$key,URL)] } {
set workflow($type,$key,color) black
} else {
set workflow($type,$key,color) grey
}
set workflow($type,$key,fontcolor) $workflow($type,$key,color)
#set workflow($type,$key,fillcolor) blue
#set workflow($type,$key,color) black
#set workflow($type,$key,style) filled
if { [string equal $type "place"] } {
switch $workflow($type,$key,${type}_key) {
start {
append workflow($type,$key,label) {S}
set workflow($type,$key,peripheries) 2
}
end {
append workflow($type,$key,label) {E}
set workflow($type,$key,peripheries) 2
}
default {
set workflow($type,$key,fontsize) 1
}
}
}
if { [string equal $type transition] && ![string equal $workflow($type,$key,trigger_type) user] } {
append workflow($type,$key,label) "\\n($workflow($type,$key,trigger_type))"
}
}
}
if { ![empty_string_p $workflow(selected_transition_key)] } {
foreach selected_transition_key $workflow(selected_transition_key) {
set workflow(transition,$selected_transition_key,color) blue
set workflow(transition,$selected_transition_key,style) filled
set workflow(transition,$selected_transition_key,fontcolor) white
}
}
if { ![empty_string_p $workflow(selected_place_key)] } {
foreach selected_place_key $workflow(selected_place_key) {
set workflow(place,$selected_place_key,color) blue
set workflow(place,$selected_place_key,style) filled
set workflow(place,$selected_place_key,fontcolor) white
}
}
set dot_text "digraph workflow {\n"
append dot_text " orientation=$orientation;\n"
append dot_text " rankdir=$rankdir;\n"
append dot_text " ratio=compress;\n"
if { [info exists size] && ![empty_string_p $size] } {
append dot_text " size=\"$size\";\n"
}
foreach place_key $workflow(places) {
set attributes [list]
foreach attr { fontsize label URL color fontname fontcolor style shape peripheries fillcolor height width fixedsize } {
if { [info exists workflow(place,$place_key,$attr)] } {
set val $workflow(place,$place_key,$attr)
regsub -all {"} $val {\"} val
lappend attributes "$attr=\"$val\""
}
}
append dot_text " node \[ [join $attributes " "] \]; \"place,$place_key\";\n"
}
foreach transition_key $workflow(transitions) {
set attributes [list]
foreach attr { fontsize label URL color fontname fontcolor style shape peripheries fillcolor height width fixedsize } {
if { [info exists workflow(transition,$transition_key,$attr)] } {
set val $workflow(transition,$transition_key,$attr)
regsub -all {"} $val {\"} val
lappend attributes "$attr=\"$val\""
}
}
append dot_text " node \[ [join $attributes " "] \]; \"transition,$transition_key\";\n"
}
foreach arc $workflow(arcs) {
set attributes [list]
set guard [ad_decode $workflow(arc,$arc,guard_description) \
"" $workflow(arc,$arc,guard_callback) $workflow(arc,$arc,guard_description)]
regsub -all {"} $guard {\"} guard
lappend attributes "label=\"[ad_decode $guard "" "" "\[ $guard \]"]\""
lappend attributes "fontname=\"$guard_font_name\""
lappend attributes "fontsize=\"$guard_font_size\""
lappend attributes "fontcolor=red"
lappend attributes "color=$workflow(arc_color)"
lappend attributes "minlen=1"
#lappend attributes "decorate=1"
append dot_text " \"$workflow(arc,$arc,from)\" -> \"$workflow(arc,$arc,to)\" \[ [join $attributes " "] \]; \n"
}
append dot_text "}"
if {$debug} { ns_log Notice "wf_generate_dot_representation: $dot_text" }
return $dot_text
}
ad_proc wf_graphviz_dot_exec {
{-output ismap}
{-to_file:boolean}
dot
} {
Implementation of wf_graphviz_dot_exec.
@author Lars Pind (lars@pinds.com)
@creation-date 29 September 2000
} {
ns_log Notice "wf_graphviz_dot_exec: -to_file=$to_file_p -output=$output dot=$dot"
set package_id [db_string package_id {select package_id from apm_packages where package_key='acs-workflow'}]
set graphviz_dot_path [im_parameter -package_id $package_id "graphviz_dot_path"]
set tmp_path [im_parameter -package_id $package_id "tmp_path"]
if { [empty_string_p $graphviz_dot_path] } {
return -code error "Graphviz is not installed."
}
set output [string tolower $output]
if { [regexp {[^a-z]} $output] } {
return -code error "Only a-z allowed in 'output'"
}
set tmp_dot [ns_mktemp "$tmp_path/dotXXXXXX"]
if { $to_file_p } {
set tmp_out [ns_mktemp "$tmp_path/outXXXXXX"]
}
# Write the DOT definition into the temporary input file
set fw [open $tmp_dot "w"]
puts -nonewline $fw $dot
close $fw
if {[catch {
if {$to_file_p} {
set result [im_exec -keepnewline $graphviz_dot_path -T$output -Gcharset=latin1 -o $tmp_out $tmp_dot]
ns_log Notice "wf_graphviz_dot_exec: im_exec -keepnewline $graphviz_dot_path -T$output -o $tmp_out $tmp_dot"
} else {
set result [im_exec -keepnewline $graphviz_dot_path -Gcharset=latin1 -T$output $tmp_dot]
ns_log Notice "wf_graphviz_dot_exec: im_exec -keepnewline $graphviz_dot_path -T$output $tmp_dot"
}
} err_msg]} {
# Check for error with graphviz 2.8
if {[regexp {Layout was not done} $err_msg match]} {
ad_return_complaint 1 "
Error executing 'dot' GraphViz:
This error message probably means that GraphViz's
plugins are not yet configured.
To configure the plugins please:
Log in as root.
Execute: dot -c
Here is the original error message:
$err_msg
"
ad_script_abort
}
if {[regexp {Format: "[^"]*" not recognized} $err_msg match]} {
ad_return_complaint 1 "
Error executing 'dot' GraphViz:
This error message probably means that your GraphViz
installtion is not complete.
You also need to install 'graphviz-gd'. For example in
RHEL/CentOS you need to execute as root:
We have encountered an error executing the GraphViz external
appliction to render your workflow graph.
Here is the detailed error message:
$err_msg
"
}
# Delete the temporary _input_ file for dot.
# (the output file remains).
file delete $tmp_dot
if { $to_file_p } {
return $tmp_out
} else {
return $result
}
}
ad_proc wf_graphviz_installed_p {} {
Will tell you whether the AT&T GraphViz package is installed or not.
Just checks to see if the parameter is set.
@author Lars Pind (lars@pinds.com)
@creation-date 29 September 2000
} {
set package_id [db_string package_id {select package_id from apm_packages where package_key='acs-workflow'}]
set graphviz_dot_path [im_parameter -package_id $package_id "graphviz_dot_path"]
return [expr ![empty_string_p $graphviz_dot_path]]
}
ad_proc wf_ismap_to_client_map {
{-name "map"}
ismap
} {
Translates a server-side imagemap as generated by graphviz into a client-side imagemap
that you can include in your HTML.
@author Lars Pind (lars@pinds.com)
@creation-date 29 September 2000
} {
set client_map "\n"
return $client_map
}
acs-workflow-master/tcl/graph-procs.xql 0000664 0000000 0000000 00000003311 14575002472 0020526 0 ustar 00root root 0000000 0000000
select pretty_name from acs_object_types where object_type = :workflow_key
select transition_key,
transition_name,
sort_order,
trigger_type
from wf_transitions
where workflow_key = :workflow_key
order by sort_order
select p.place_key,
p.place_name,
p.sort_order
from wf_places p
where p.workflow_key = :workflow_key
order by p.sort_order
select transition_key,
place_key,
direction,
guard_callback,
guard_custom_arg,
guard_description
from wf_arcs
where workflow_key = :workflow_key
select package_id from apm_packages where package_key='acs-workflow'
select package_id from apm_packages where package_key='acs-workflow'
select package_id from apm_packages where package_key='acs-workflow'
acs-workflow-master/tcl/intranet-workflow-procs.tcl 0000664 0000000 0000000 00000000506 14575002472 0023102 0 ustar 00root root 0000000 0000000 ad_library {
]project-open[ specific extension for acs-workflow.
I guess that these extensions are not reall ]project-open[ specific,
but mainly reference the issue of integration with other packages.
@author Frank Bergmann (frank.bergmann@project-open.com)
@creation-date 2006-03-16
@cvs-id $Id$
}
acs-workflow-master/tcl/wizard-procs.tcl 0000664 0000000 0000000 00000015103 14575002472 0020705 0 ustar 00root root 0000000 0000000 ad_library {
Helper-procs for the process wizard.
@author Lars Pind (lars@pinds.com)
@creation-date 28 September 2000
@cvs-id $Id$
}
ad_proc wf_name_to_key {
name
} {
Generates a key from a name by making it all lowercase, removing
non-letters and putting in underscores instead of spaces.
@author Lars Pind (lars@pinds.com)
@creation-date 29 September, 2000
} {
regsub -all { } $name {_} key
set key [string tolower $key]
regsub -all {[^a-z0-9_]} $key {} key
return $key
}
ad_proc wf_valid_key_p {
key
} {
Check that a value is valid as a key for a workflow/transition/place in
a workflow definition.
@author Lars Pind (lars@pinds.com)
@creation-date 1 November, 2000
} {
return [string is wordchar]
}
ad_proc wf_make_unique {
-maxlen:required
-taken_names:required
name_part_one
{name_part_two ""}
} {
Takes a name (split in two parts) and makes it unique with respect to the list passed in taken_names,
by putting an integer number between name_part_one
and name_part_two, chopping name_part_one as required to stay within maxlen.
@author Lars Pind (lars@pinds.com)
@creation-date 29 September, 2000
} {
set len_one [string length $name_part_one]
set len_two [string length $name_part_two]
if { $len_one + $len_two > $maxlen } {
set name_part_one [string range $name_part_one 0 [expr $maxlen-$len_two-1]]
set len_one [string length $name_part_one]
}
if { [lsearch -exact $taken_names "$name_part_one$name_part_two"] == -1 } {
return "$name_part_one$name_part_two"
} else {
set num_taken_names [llength $taken_names]
set number 2
while 1 {
set len_num [string length $number]
if { $len_one + $len_num + $len_two > $maxlen } {
set name_part_one [string range $name_part_one 0 [expr $maxlen-$len_two-$len_num-1]]
set len_one [string length $name_part_one]
}
if { [lsearch -exact $taken_names "$name_part_one$number$name_part_two"] == -1 } {
return "$name_part_one$number$name_part_two"
}
incr number
if { $number > $num_taken_names + 2 } {
return -code error "Infinite loop"
}
}
}
}
ad_proc wf_simple_wizard_process_def {} {
Gives the process definition list for use with wf_progress_bar
@author Lars Pind (lars@pinds.com)
@creation-date 29 September, 2000
} {
return {
{"" "Name"}
{"tasks" "Tasks"}
{"loops" "Loops"}
{"assignments" "Assignments"}
{"create" "Done!"}
}
}
ad_proc wf_progress_bar {
{-nolinks:boolean}
{-name}
process_def
num_completed
} {
Returns an HTML fragment that displays the progress of a wizard nicely.
@param process_def a list of two-tuples, with the first value being the URL to link to, the second the name to display.
@param num_completed the number of steps completed so far. When you're at the first step, this would be 0.
@author Lars Pind (lars@pinds.com)
@creation-date 29 September, 2000
} {
set steps {}
set counter 0
foreach step $process_def {
if { $counter < $num_completed } {
if { !$nolinks_p } {
lappend steps "
"
return $html
}
ad_proc wf_wizard_massage_tasks {
the_tasks
list_var
array_var
{multirow_var ""}
} {
We store tasks in a client property as a list of array gets
with the keys: task_name, transition_key, task_time, loop_to_transition_key, loop_question, loop_answer,
assigning_transition_key.
This proc massages that into three vars:
a list of transition_keys, which lays out the sequence of transitions,
and an array that holds all the information, keyed by
($transition_key,key) where key is one of the above keys.
Finally, a multirow datasource, containing the tasks.
@author Lars Pind (lars@pinds.com)
@creation-date 29 September, 2000
} {
# Note also: This whole way of representing the information here in three or four different formats,
# actually sucks.
# Don't do this if you happen to be porting this to a real language (e.g., Java)
if { ![empty_string_p $list_var] } {
upvar 1 $list_var the_list
}
if { ![empty_string_p $array_var] } {
upvar 1 $array_var the_array
}
set the_list {}
array unset the_array *
if { ![empty_string_p $multirow_var] } {
template::multirow create $multirow_var transition_key task_name \
task_time \
loop_to_transition_key loop_to_task_name loop_question loop_answer \
assigning_transition_key assigning_task_name
}
set the_array(,task_name) ""
foreach task_info $the_tasks {
array set task $task_info
set transition_key $task(transition_key)
lappend the_list $transition_key
foreach name { transition_key task_name task_time loop_to_transition_key loop_question loop_answer assigning_transition_key } {
if { [info exists task($name)] } {
set the_array($transition_key,$name) $task($name)
} else {
set the_array($transition_key,$name) ""
}
}
if { ![empty_string_p $multirow_var] } {
template::multirow append $multirow_var \
$transition_key \
$the_array($transition_key,task_name) \
$the_array($transition_key,task_time) \
$the_array($transition_key,loop_to_transition_key) \
$the_array($the_array($transition_key,loop_to_transition_key),task_name) \
$the_array($transition_key,loop_question) \
$the_array($transition_key,loop_answer) \
$the_array($transition_key,assigning_transition_key) \
$the_array($the_array($transition_key,assigning_transition_key),task_name)
}
}
}
acs-workflow-master/tcl/workflow-init.tcl 0000664 0000000 0000000 00000000703 14575002472 0021074 0 ustar 00root root 0000000 0000000 ad_library {
Initialization code for the acs-workflow package
(to run once on server startup).
@cvs-id $Id$
}
# normal rhythm: Every 15 minutes
# ad_schedule_proc -thread t 900 wf_sweep_time_events
set interval [parameter::get \
-package_id [apm_package_id_from_key "acs-workflow"] \
-parameter SweepTimeEventsInterval -default 303]
# for debugging: every 1 minute
ad_schedule_proc -thread t $interval wf_sweep_time_events
acs-workflow-master/tcl/workflow-procs-oracle.xql 0000664 0000000 0000000 00000053061 14575002472 0022551 0 ustar 00root root 0000000 0000000
oracle8.1.6
select case_id,
acs_object.name(object_id) as object_name,
state
from wf_cases
where case_id = :case_id
select t.task_id,
t.case_id,
c.object_id,
acs_object.name(c.object_id) as object_name,
ot.pretty_name as object_type_pretty,
c.workflow_key,
tr.transition_name as task_name,
tr.instructions,
t.state,
t.enabled_date,
to_char(t.enabled_date, :date_format) as enabled_date_pretty,
t.started_date,
to_char(t.started_date, :date_format) as started_date_pretty,
t.canceled_date,
to_char(t.canceled_date, :date_format) as canceled_date_pretty,
t.finished_date,
to_char(t.finished_date, :date_format) as finished_date_pretty,
t.overridden_date,
to_char(t.overridden_date, :date_format) as overridden_date_pretty,
t.holding_user,
acs_object.name(t.holding_user) as holding_user_name,
p.email as holding_user_email,
t.hold_timeout,
to_char(t.hold_timeout, :date_format) as hold_timeout_pretty,
t.deadline,
to_char(t.deadline, :date_format) as deadline_pretty,
t.deadline - sysdate as days_till_deadline,
tr.estimated_minutes,
sysdate
from wf_tasks t,
wf_cases c,
wf_transition_info tr,
acs_objects o,
acs_object_types ot,
parties p
where t.task_id = :task_id
and c.case_id = t.case_id
and tr.transition_key = t.transition_key
and tr.workflow_key = t.workflow_key and tr.context_key = c.context_key
and o.object_id = c.object_id
and ot.object_type = o.object_type
and p.party_id (+) = t.holding_user
select a.attribute_id,
a.attribute_name,
a.pretty_name,
a.datatype,
acs_object.get_attribute(t.case_id, a.attribute_name) as value,
'' as attribute_widget
from acs_attributes a, wf_transition_attribute_map m, wf_tasks t
where t.task_id = :task_id
and m.workflow_key = t.workflow_key and m.transition_key = t.transition_key
and a.attribute_id = m.attribute_id
order by m.sort_order
select ut.user_id,
acs_object.name(ut.user_id) as name,
p.email as email
from wf_user_tasks ut, parties p
where ut.task_id = :task_id
and p.party_id = ut.user_id
select j.journal_id,
j.action,
j.action_pretty,
o.creation_date,
to_char(o.creation_date, :date_format) as creation_date_pretty,
o.creation_user,
acs_object.name(o.creation_user) as creation_user_name,
p.email as creation_user_email,
o.creation_ip,
j.msg
from journal_entries j, acs_objects o, parties p
where j.object_id = :case_id
and o.object_id = j.journal_id
and p.party_id (+) = o.creation_user
order by o.creation_date $sql_order
begin
:1 := workflow_case.begin_task_action(
task_id => :task_id,
action => :action,
action_ip => :modifying_ip,
user_id => :user_id,
msg => :msg);
end;
begin
workflow_case.set_attribute_value(
journal_id => :journal_id,
attribute_name => :attribute_name,
value => :value
);
end;
begin
workflow_case.clear_manual_assignments(
case_id => :case_id,
role_key => :role_key
);
end;
begin
workflow_case.add_manual_assignment(
case_id => :case_id,
role_key => :role_key,
party_id => :party_id
);
end;
begin
workflow_case.end_task_action(
journal_id => :journal_id,
action => :action,
task_id => :task_id
);
end;
begin
workflow_case.fire_message_transition(
task_id => :task_id
);
end;
begin
:1 := workflow_case.new(case_id => :case_id,
workflow_key => :workflow_key,
context_key => :context_key,
object_id => :object_id,
creation_user => :user_id,
creation_ip => :creation_ip
);
end;
begin workflow_case.start_case(case_id => :case_id,
creation_user => :user_id,
creation_ip => :creation_ip
); end;
begin
workflow_case.suspend(
case_id => :case_id,
user_id => :user_id,
ip_address => :ip_address,
msg => :msg
);
end;
begin
workflow_case.resume(
case_id => :case_id,
user_id => :user_id,
ip_address => :ip_address,
msg => :msg
);
end;
begin
workflow_case.cancel(
case_id => :case_id,
user_id => :user_id,
ip_address => :ip_address,
msg => :msg
);
end;
begin
:1 := journal_entry.new(
object_id => :case_id,
action => 'comment',
creation_user => :user_id,
creation_ip => :ip_address,
msg => :msg
);
end;
begin
workflow_case.add_manual_assignment(
case_id => :case_id,
role_key => :role_key,
party_id => :party_id
);
end;
begin
workflow_case.remove_manual_assignment(
case_id => :case_id,
role_key => :role_key,
party_id => :party_id
);
end;
begin
workflow_case.clear_manual_assignments(
case_id => :case_id,
role_key => :role_key
);
end;
begin
workflow_case.add_task_assignment(
task_id => :task_id,
party_id => :party_id,
permanent_p => :permanent_value
);
end;
begin
workflow_case.remove_task_assignment(
task_id => :task_id,
party_id => :party_id,
permanent_p => :permanent_value
);
end;
begin
workflow_case.clear_task_assignments(
task_id => :task_id,
permanent_p => :permanent_value
);
end;
begin
workflow_case.set_case_deadline(
case_id => :case_id,
transition_key => :transition_key,
deadline => :deadline
);
end;
begin
workflow_case.remove_case_deadline(
case_id => :case_id,
transition_key => :transition_key
);
end;
begin
workflow.add_place(
workflow_key => :workflow_key,
place_key => :place_key,
place_name => :place_name,
sort_order => :sort_order
);
end;
begin
workflow.delete_place(
workflow_key => :workflow_key,
place_key => :place_key
);
end;
begin
workflow.add_role(
workflow_key => :workflow_key,
role_key => :role_key,
role_name => :role_name,
sort_order => :sort_order
);
end;
begin
workflow.move_role_up(
workflow_key => :workflow_key,
role_key => :role_key
);
end;
begin
workflow.move_role_down(
workflow_key => :workflow_key,
role_key => :role_key
);
end;
begin
workflow.delete_role(
workflow_key => :workflow_key,
role_key => :role_key
);
end;
begin
workflow.add_transition(
workflow_key => :workflow_key,
transition_key => :transition_key,
transition_name => :transition_name,
role_key => :role_key,
sort_order => :sort_order,
trigger_type => :trigger_type
);
end;
begin
workflow.delete_transition(
workflow_key => :workflow_key,
transition_key => :transition_key
);
end;
begin
workflow.add_arc(
workflow_key => :workflow_key,
transition_key => :transition_key,
place_key => :place_key,
direction => :direction,
guard_callback => :guard_callback,
guard_custom_arg => :guard_custom_arg,
guard_description => :guard_description
);
end;
begin
workflow.add_arc(
workflow_key => :workflow_key,
transition_key => :from_transition_key,
place_key => :to_place_key,
guard_callback => :guard_callback,
guard_custom_arg => :guard_custom_arg,
guard_description => :guard_description
);
end;
begin
workflow.add_arc(
workflow_key => :workflow_key,
transition_key => :to_transition_key,
place_key => :from_place_key
);
end;
begin
workflow.delete_arc(
workflow_key => :workflow_key,
transition_key => :transition_key,
place_key => :place_key,
direction => :direction
);
end;
begin
workflow.add_trans_attribute_map(
workflow_key => :workflow_key,
transition_key => :transition_key,
attribute_id => :attribute_id,
sort_order => :sort_order
);
end;
begin
workflow.add_trans_attribute_map(
workflow_key => :workflow_key,
transition_key => :transition_key,
attribute_name => :attribute_name,
sort_order => :sort_order
);
end;
begin
workflow.delete_trans_attribute_map(
workflow_key => :workflow_key,
transition_key => :transition_key,
attribute_id => :attribute_id
);
end;
begin
workflow.add_trans_role_assign_map(
workflow_key => :workflow_key,
transition_key => :transition_key,
assign_role_key => :assign_role_key
);
end;
begin
workflow.delete_trans_role_assign_map(
workflow_key => :workflow_key,
transition_key => :transition_key,
assign_role_key => :assign_role_key
);
end;
begin :1 := workflow.simple_p(:workflow_key); end;
declare
v_workflow_key varchar2(40);
begin
v_workflow_key := workflow.create_workflow(
workflow_key => '[db_quote $new_workflow_key]',
pretty_name => '[db_quote $new_workflow_pretty_name]',
pretty_plural => '[db_quote $new_workflow_pretty_plural]',
description => '[db_quote $description]',
table_name => '[db_quote $new_table_name]'
);
end;
/
show errors
begin
workflow.add_place(
workflow_key => '[db_quote $new_workflow_key]',
place_key => '[db_quote $place_key]',
place_name => '[db_quote $place_name]',
sort_order => [ad_decode $sort_order "" "null" $sort_order]
);
end;
/
show errors
begin
workflow.add_role(
workflow_key => '[db_quote $new_workflow_key]',
role_key => '[db_quote $role_key]',
role_name => '[db_quote $role_name]',
sort_order => [ad_decode $sort_order "" "null" $sort_order]
);
end;
/
show errors
begin
workflow.add_transition(
workflow_key => '[db_quote $new_workflow_key]',
transition_key => '[db_quote $transition_key]',
transition_name => '[db_quote $transition_name]',
role_key => '[db_quote $role_key]',
sort_order => [ad_decode $sort_order "" "null" $sort_order],
trigger_type => '[db_quote $trigger_type]'
);
end;
/
show errors
begin
workflow.add_arc(
workflow_key => '[db_quote $new_workflow_key]',
transition_key => '[db_quote $transition_key]',
place_key => '[db_quote $place_key]',
direction => '[db_quote $direction]',
guard_callback => '[db_quote $guard_callback]',
guard_custom_arg => '[db_quote $guard_custom_arg]',
guard_description => '[db_quote $guard_description]'
);
end;
/
show errors
declare
v_attribute_id number;
begin
v_attribute_id := workflow.create_attribute(
workflow_key => '[db_quote $new_workflow_key]',
attribute_name => '[db_quote $attribute_name]',
datatype => '[db_quote $datatype]',
pretty_name => '[db_quote $pretty_name]',
default_value => '[db_quote $default_value]'
);
end;
/
show errors
begin
workflow.add_trans_attribute_map(
workflow_key => '[db_quote $new_workflow_key]',
transition_key => '[db_quote $transition_key]',
attribute_name => '[db_quote $attribute_name]',
sort_order => [ad_decode $sort_order "" "null" $sort_order]
);
end;
/
show errors
begin
workflow.add_trans_role_assign_map(
workflow_key => '[db_quote $new_workflow_key]',
transition_key => '[db_quote $transition_key]',
assign_role_key => '[db_quote $assign_role_key]'
);
end;
/
show errors;
begin
workflow_case.sweep_timed_transitions;
end;
begin
workflow_case.sweep_hold_timeout;
end;
acs-workflow-master/tcl/workflow-procs-postgresql.xql 0000664 0000000 0000000 00000043655 14575002472 0023517 0 ustar 00root root 0000000 0000000
postgresql7.1
select case_id,
acs_object__name(object_id) as object_name,
state
from wf_cases
where case_id = :case_id
select t.task_id,
t.case_id,
c.object_id,
acs_object__name(c.object_id) as object_name,
ot.pretty_name as object_type_pretty,
c.workflow_key,
tr.transition_key,
tr.transition_name as task_name,
tr.instructions,
t.state,
t.enabled_date,
to_char(t.enabled_date, :date_format) as enabled_date_pretty,
t.started_date,
to_char(t.started_date, :date_format) as started_date_pretty,
t.canceled_date,
to_char(t.canceled_date, :date_format) as canceled_date_pretty,
t.finished_date,
to_char(t.finished_date, :date_format) as finished_date_pretty,
t.overridden_date,
to_char(t.overridden_date, :date_format) as overridden_date_pretty,
t.holding_user,
acs_object__name(t.holding_user) as holding_user_name,
p.email as holding_user_email,
t.hold_timeout,
to_char(t.hold_timeout, :date_format) as hold_timeout_pretty,
t.deadline,
to_char(t.deadline, :date_format) as deadline_pretty,
t.deadline - current_timestamp as days_till_deadline,
tr.estimated_minutes,
current_timestamp
from wf_tasks t left outer join parties p
on p.party_id = t.holding_user,
wf_cases c,
wf_transition_info tr,
acs_objects o,
acs_object_types ot
where t.task_id = :task_id
and c.case_id = t.case_id
and tr.transition_key = t.transition_key
and tr.workflow_key = t.workflow_key and tr.context_key = c.context_key
and o.object_id = c.object_id
and ot.object_type = o.object_type
select a.attribute_id,
a.attribute_name,
a.pretty_name,
a.datatype,
acs_object__get_attribute(t.case_id, a.attribute_name) as value,
'' as attribute_widget
from acs_attributes a, wf_transition_attribute_map m, wf_tasks t
where t.task_id = :task_id
and m.workflow_key = t.workflow_key and m.transition_key = t.transition_key
and a.attribute_id = m.attribute_id
order by m.sort_order
select ut.user_id,
acs_object__name(ut.user_id) as name,
p.email as email
from wf_user_tasks ut, parties p
where ut.task_id = :task_id
and p.party_id = ut.user_id
select j.journal_id,
j.action,
j.action_pretty,
o.creation_date,
to_char(o.creation_date, :date_format) as creation_date_pretty,
o.creation_user,
acs_object__name(o.creation_user) as creation_user_name,
p.email as creation_user_email,
o.creation_ip,
j.msg
from journal_entries j, acs_objects o left outer join parties p
on p.party_id = o.creation_user
where j.object_id = :case_id
and o.object_id = j.journal_id
order by o.creation_date $sql_order
select workflow_case__begin_task_action (
:task_id,
:action,
:modifying_ip,
:user_id,
:msg);
select workflow_case__set_attribute_value (
:journal_id,
:attribute_name,
:value
);
select workflow_case__clear_manual_assignments (
:case_id,
:role_key
);
select workflow_case__add_manual_assignment (
:case_id,
:role_key,
:party_id
);
select workflow_case__end_task_action (
:journal_id,
:action,
:task_id
);
select workflow_case__fire_message_transition (
:task_id
);
select workflow_case__new (
:case_id,
:workflow_key,
:context_key,
:object_id,
now(),
:user_id,
:creation_ip
);
select workflow_case__start_case (
:case_id,
:user_id,
:creation_ip,
null
);
select workflow_case__suspend (
:case_id,
:user_id,
:ip_address,
:msg
);
select workflow_case__resume (
:case_id,
:user_id,
:ip_address,
:msg
);
select workflow_case__cancel (
:case_id,
:user_id,
:ip_address,
:msg
);
select journal_entry__new (
null,
:case_id,
'comment',
null,
now(),
:user_id,
:ip_address,
:msg
)
select workflow_case__add_manual_assignment (
:case_id,
:role_key,
:party_id
);
select workflow_case__remove_manual_assignment (
:case_id,
:role_key,
:party_id
);
select workflow_case__clear_manual_assignments (
:case_id,
:role_key
);
select workflow_case__add_task_assignment (
:task_id,
:party_id,
:permanent_value
);
select workflow_case__remove_task_assignment (
:task_id,
:party_id,
:permanent_value
);
select workflow_case__clear_task_assignments (
:task_id,
:permanent_value
);
select workflow_case__set_case_deadline (
:case_id,
:transition_key,
:deadline
);
select workflow_case__remove_case_deadline (
:case_id,
:transition_key
);
select workflow__add_place (
:workflow_key,
:place_key,
:place_name,
:sort_order
);
select workflow__delete_place (
:workflow_key,
:place_key
);
select workflow__add_role (
:workflow_key,
:role_key,
:role_name,
:sort_order
);
select workflow__move_role_up (
:workflow_key,
:role_key
);
select workflow__move_role_down (
:workflow_key,
:role_key
);
select workflow__delete_role (
:workflow_key,
:role_key
);
select workflow__add_transition (
:workflow_key,
:transition_key,
:transition_name,
:role_key,
:sort_order,
:trigger_type
);
select workflow__delete_transition (
:workflow_key,
:transition_key
);
select workflow__add_arc (
:workflow_key,
:transition_key,
:place_key,
:direction,
:guard_callback,
:guard_custom_arg,
:guard_description
);
select workflow__add_arc (
:workflow_key,
:from_transition_key,
:to_place_key,
:guard_callback,
:guard_custom_arg,
:guard_description
);
select workflow__add_arc (
:workflow_key,
:from_place_key,
:to_transition_key
);
select workflow__delete_arc (
:workflow_key,
:transition_key,
:place_key,
:direction
);
select workflow__add_trans_attribute_map (
:workflow_key,
:transition_key,
:attribute_id,
:sort_order
);
select workflow__add_trans_attribute_map (
:workflow_key,
:transition_key,
:attribute_name,
:sort_order
);
select workflow__delete_trans_attribute_map (
:workflow_key,
:transition_key,
:attribute_id
);
select workflow__add_trans_role_assign_map (
:workflow_key,
:transition_key,
:assign_role_key
);
select workflow__delete_trans_role_assign_map (
:workflow_key,
:transition_key,
:assign_role_key
);
select workflow__simple_p(:workflow_key);
create function inline_0 () returns integer as '
begin
PERFORM workflow__create_workflow (
''[db_quote [db_quote $new_workflow_key]]'',
''[db_quote [db_quote $new_workflow_pretty_name]]'',
''[db_quote [db_quote $new_workflow_pretty_plural]]'',
''[db_quote [db_quote $description]]'',
''[db_quote [db_quote $new_table_name]]'',
''case_id''
);
return null;
end;' language 'plpgsql';
select inline_0 ();
drop function inline_0 ();
select workflow__add_place(
'[db_quote $new_workflow_key]',
'[db_quote $place_key]',
'[db_quote $place_name]',
[ad_decode $sort_order "" "null" $sort_order]
);
select workflow__add_role (
'[db_quote $new_workflow_key]',
'[db_quote $role_key]',
'[db_quote $role_name]',
[ad_decode $sort_order "" "null" $sort_order]
);
select workflow__add_transition (
'[db_quote $new_workflow_key]',
'[db_quote $transition_key]',
'[db_quote $transition_name]',
[ad_decode $role_key "" null '[db_quote $role_key]'],
[ad_decode $sort_order "" "null" $sort_order],
'[db_quote $trigger_type]'
);
select workflow__add_arc (
'[db_quote $new_workflow_key]',
'[db_quote $transition_key]',
'[db_quote $place_key]',
'[db_quote $direction]',
'[db_quote $guard_callback]',
'[db_quote $guard_custom_arg]',
'[db_quote $guard_description]'
);
select workflow__create_attribute(
'[db_quote $new_workflow_key]',
'[db_quote $attribute_name]',
'[db_quote $datatype]',
'[db_quote $pretty_name]',
null,
null,
null,
'[db_quote $default_value]',
1,
1,
null,
'generic'
);
select workflow__add_trans_attribute_map(
'[db_quote $new_workflow_key]',
'[db_quote $transition_key]',
'[db_quote $attribute_name]',
[ad_decode $sort_order "" "null" $sort_order]
);
select workflow__add_trans_role_assign_map(
'[db_quote $new_workflow_key]',
'[db_quote $transition_key]',
'[db_quote $assign_role_key]'
);
select workflow_case__sweep_timed_transitions();
select workflow_case__sweep_hold_timeout();
acs-workflow-master/tcl/workflow-procs.tcl 0000664 0000000 0000000 00000142051 14575002472 0021262 0 ustar 00root root 0000000 0000000 # /packages/acs-workflow/tcl/workflow-procs.tcl
ad_library {
Tcl-API for the workflow engine.
@author Lars Pind (lars@pinds.com)
@creation-date 13 July 2000
@cvs-id $Id$
}
ad_proc -public wf_task_list {
{-date_format "Mon fmDDfm, YYYY HH24:MI:SS"}
{-user_id ""}
{-type enabled}
} {
Get information about the tasks are on a user's work list.
@param user_id is the user for which we're listing tasks. If you
don't provide a user_id or
you provide an empty string for user_id, then we'll use the
user_id of the currently logged-in user.
@param date_format Use this to customize the date-format
used. Must be a valid Oracle date format specification.
@param type is either enabled or own:
enabled
Returns the list of tasks that are ready to execute, but not
started by anyone yet.
own
Returns the list of tasks currently started and held by the given user.
@return a Tcl list of information about the tasks that are
executable by the given user, ordered by their priority.
Each element of the list is an [array get] representation with the following
keys: task_id, case_id, transition_key, task_name, enabled_date, enabled_date_pretty,
started_date, started_date_pretty, deadline, deadline_pretty, state, object_id, object_type, object_type_pretty,
object_name, estimated_minutes, sysdate.
Sysdate is provided, so you can calculate the number of days
between now and any of the other dates provided.
@author Lars Pind (lars@pinds.com)
@creation-date 10 July, 2000
} {
if { ![string equal $type enabled] && ![string equal $type own] } {
return -code error "Unrecognized type: Type can be 'enabled' or 'own'"
}
if { [empty_string_p $user_id] } {
set user_id [ad_conn user_id]
if { $user_id == 0 } {
return {}
}
}
set select {
{t.task_id}
{t.case_id}
{t.transition_key}
{t.transition_name as task_name}
{t.enabled_date}
{to_char(t.enabled_date, :date_format) as enabled_date_pretty}
{t.started_date}
{to_char(t.started_date, :date_format) as started_date_pretty}
{t.deadline}
{to_char(t.deadline, :date_format) as deadline_pretty}
{t.deadline - sysdate as days_till_deadline}
{t.state}
{c.object_id}
{ot.object_type as object_type}
{ot.pretty_name as object_type_pretty}
{acs_object.name(c.object_id) as object_name}
{t.estimated_minutes}
{c.workflow_key}
{wft.pretty_name as workflow_name}
{sysdate}
}
set from {
{wf_user_tasks t}
{wf_cases c}
{acs_objects o}
{acs_object_types ot}
{acs_object_types wft}
}
set where {
{t.user_id = :user_id}
{c.case_id = t.case_id}
{c.object_id = o.object_id}
{ot.object_type = o.object_type}
{wft.object_type = c.workflow_key}
}
switch $type {
enabled {
lappend where {t.state = 'enabled'}
}
own {
lappend from {users u}
lappend where {t.state = 'started'} {t.holding_user = t.user_id} {u.user_id = t.user_id}
}
}
set sql "
select [join $select ",\n "]
from [join $from ",\n "]
where [join $where "\n and "]
"
db_foreach user_tasks $sql -column_array row {
lappend result [array get row]
} if_no_rows {
set result [list]
}
return $result
}
ad_proc -public wf_case_info {
case_id
} {
Get information about a case.
@return A list in array get format with the following keys: case_id, object_name, state.
@author Lars Pind (lars@pinds.com)
@creation-date 10 July, 2000
} {
db_1row case {
select case_id,
acs_object.name(object_id) as object_name,
state
from wf_cases
where case_id = :case_id
} -column_array case
return [array get case]
}
ad_proc -public wf_task_info {
{-date_format "Mon fmDDfm, YYYY HH24:MI:SS"}
task_id
} {
Get detailed information about one task.
@param date_format Use this to customize the date-format
used. Must be a valid Oracle date format specification.
@return an [array get] representation with the following keys:
task_id, case_id, object_id, object_name, object_type_pretty, workflow_key, task_name,
state, state_pretty, enabled_date, enabled_date_pretty, started_date, started_date_pretty,
canceled_date, canceled_date_pretty, finished_date, finished_date_pretty,
overridden_date, overridden_date_pretty, holding_user, holding_user_name,
holding_user_email, hold_timeout, hold_timeout_pretty, deadline, deadline_pretty, days_till_deadline
estimated_minutes, instructions, sysdate, journal, attributes_to_set, assigned_users,
this_user_is_assigned_p, roles_to_assign.
The values for the keys journal, attributes_to_set and assigned_users
are themselves Tcl lists of [array
get] repesentations. For the journal entry, see wf_journal.
The key attribute_to_set contains these keys: attribute_id, attribute_name,
pretty_name, datatype, value, wf_datatype.
The key assigned_users contains these keys: user_id, name, email.
The key transitions_to_assign contains these keys: transition_key, transition_name
Sysdate is provided, so you can calculate the number of days
between now and any of the other dates provided.
@author Lars Pind (lars@pinds.com)
@creation-date 10 July, 2000
} {
db_1row task {
select t.task_id,
t.case_id,
c.object_id,
acs_object.name(c.object_id) as object_name,
ot.pretty_name as object_type_pretty,
c.workflow_key,
tr.transition_key,
tr.transition_name as task_name,
tr.instructions,
t.state,
t.enabled_date,
to_char(t.enabled_date, :date_format) as enabled_date_pretty,
t.started_date,
to_char(t.started_date, :date_format) as started_date_pretty,
t.canceled_date,
to_char(t.canceled_date, :date_format) as canceled_date_pretty,
t.finished_date,
to_char(t.finished_date, :date_format) as finished_date_pretty,
t.overridden_date,
to_char(t.overridden_date, :date_format) as overridden_date_pretty,
t.holding_user,
acs_object.name(t.holding_user) as holding_user_name,
p.email as holding_user_email,
t.hold_timeout,
to_char(t.hold_timeout, :date_format) as hold_timeout_pretty,
t.deadline,
to_char(t.deadline, :date_format) as deadline_pretty,
t.deadline - sysdate as days_till_deadline,
tr.estimated_minutes,
sysdate
from wf_tasks t,
wf_cases c,
wf_transition_info tr,
acs_objects o,
acs_object_types ot,
parties p
where t.task_id = :task_id
and c.case_id = t.case_id
and tr.transition_key = t.transition_key
and tr.workflow_key = t.workflow_key and tr.context_key = c.context_key
and o.object_id = c.object_id
and ot.object_type = o.object_type
and p.party_id (+) = t.holding_user
} -column_array task
set task(state_pretty) [wf_task_state_pretty $task(state)]
db_multirow task_attributes_to_set task_attributes_to_set {
select a.attribute_id,
a.attribute_name,
a.pretty_name,
a.datatype,
acs_object.get_attribute(t.case_id, a.attribute_name) as value,
'' as attribute_widget
from acs_attributes a, wf_transition_attribute_map m, wf_tasks t
where t.task_id = :task_id
and m.workflow_key = t.workflow_key and m.transition_key = t.transition_key
and a.attribute_id = m.attribute_id
order by m.sort_order
} {
set attribute_widget [wf_attribute_widget \
[list attribute_id $attribute_id \
attribute_name $attribute_name \
pretty_name $pretty_name \
datatype $datatype \
value $value]]
}
db_multirow task_roles_to_assign task_roles_to_assign {
select r.role_key,
r.role_name,
'' as assignment_widget
from wf_tasks t, wf_transition_role_assign_map tram, wf_roles r
where t.task_id = :task_id
and tram.workflow_key = t.workflow_key and tram.transition_key = t.transition_key
and r.workflow_key = tram.workflow_key and r.role_key = tram.assign_role_key
order by r.sort_order
} {
set assignment_widget [wf_assignment_widget -case_id $task(case_id) $role_key]
}
db_multirow task_assigned_users task_assigned_users {
select ut.user_id,
acs_object.name(ut.user_id) as name,
p.email as email
from wf_user_tasks ut, parties p
where ut.task_id = :task_id
and p.party_id = ut.user_id
}
set user_id [ad_conn user_id]
if { [string equal $task(state) enabled] } {
set task(this_user_is_assigned_p) [db_string this_user_is_assigned_p {
select count(*) from wf_user_tasks where task_id = :task_id and user_id = :user_id
}]
} else {
if { ![empty_string_p $task(holding_user)] && $user_id == $task(holding_user) } {
set task(this_user_is_assigned_p) 1
} else {
set task(this_user_is_assigned_p) 0
}
}
return [array get task]
}
ad_proc -public wf_task_panels {
-task_id:required
-action:boolean
-target
{-user_id 0}
} {
Add the panels for a task into the multirow target. Action
panels follow non-action panels. These could be returned by wf_task_info
in the future with a little rewriting of the workflow pages.
@param task_id The task in question
@param action Only return action panels
@param target The multirow target
@param user_id Return "show only when task started" panels for this user
@author Don Baccus (dhogaza@pacifier.com)
} {
if { $action_p } {
db_multirow $target action_panels ""
} else {
db_multirow $target all_panels ""
}
}
ad_proc -public wf_journal {
{-date_format "Mon fmDDfm, YYYY HH24:MI:SS"}
{-order latest_first}
case_id
} {
Get the journal for a case.
@param date_format Use this to customize the date-format
used. Must be a valid Oracle date format specification.
@param order Either latest_first or latest_last.
@return an [array get] form containin two keys:
case_id and entries.
The entries key holds a Tcl list of [array
get] representations with the following keys:
journal_id, action, action_pretty, creation_date, creation_date_pretty,
creation_user, creation_user_name, creation_user_email, creation_ip, msg, attributes.
The key attributes contains a Tcl list of [array get] representations with
these keys: name, pretty_name, datatype, wf_datatype, value.
@author Lars Pind (lars@pinds.com)
@creation-date 10 July, 2000
} {
switch -- $order {
latest_first {
set sql_order "desc"
}
latest_last {
set sql_order "asc"
}
default {
return -code error "Order must be latest_first or latest_last"
}
}
set entries [list]
db_foreach journal "
select j.journal_id,
j.action,
j.action_pretty,
o.creation_date,
to_char(o.creation_date, :date_format) as creation_date_pretty,
o.creation_user,
acs_object.name(o.creation_user) as creation_user_name,
p.email as creation_user_email,
o.creation_ip,
j.msg
from journal_entries j, acs_objects o, parties p
where j.object_id = :case_id
and o.object_id = j.journal_id
and p.party_id (+) = o.creation_user
order by o.creation_date $sql_order
" -column_array entry {
set entry(attributes) [list]
set journal_id $entry(journal_id)
db_foreach attributes {
select a.attribute_name as name,
a.pretty_name,
a.datatype,
v.attr_value as value
from wf_attribute_value_audit v, acs_attributes a
where v.journal_id = :journal_id
and a.attribute_id = v.attribute_id
} -column_array attribute {
lappend entry(attributes) [array get attribute]
}
set entry(attributes_html) [join $entry(attributes) " "]
lappend entries [array get entry]
}
return [list case_id $case_id entries $entries]
}
ad_proc -public wf_workflow_info {
workflow_key
} {
Get the definition of a workflow.
@return an [array get] representation with the following keys:
workflow_name, description, start_place, end_place, transitions.
The value of transitions is a Tcl list of
[array get] representations, with these keys:
transition_key, transition_name, sort_order, attributes.
The attributes is also a Tcl list of [array get] with
these keys: attribute_name.
@author Lars Pind (lars@pinds.com)
@creation-date 10 July, 2000
} {
db_1row workflow {
select t.pretty_name,
w.description
from wf_workflows w, acs_object_types t
where w.workflow_key = :workflow_key
and t.object_type = w.workflow_key
} -column_array workflow_info
set workflow_info(transitions) [list]
db_foreach transitions {
select transition_key, transition_name, sort_order
from wf_transitions
where workflow_key = :workflow_key
and trigger_type = 'user'
order by sort_order asc
} -column_array transition_info {
set attributes [list]
set transition_key $transition_info(transition_key)
db_foreach attributes {
select a.attribute_name
from wf_transition_attribute_map m, acs_attributes a
where m.workflow_key = :workflow_key
and m.transition_key = :transition_key
and a.attribute_id = m.attribute_id
} -column_array attribute_info {
lappend attributes [array get attribute_info]
}
set transition_info(attributes) $attributes
lappend workflow_info(transitions) [array get transition_info]
}
# get places ...
return [array get workflow_info]
}
ad_proc -public wf_task_action {
-user_id
{-msg ""}
-attributes
-assignments
task_id
action
} {
Tells the workflow engine that the given action has been taken.
The workflow state will be updated accordingly.
@param action one of 'start', 'cancel', 'finish' or
'comment'. Comment doesn't change the state of the workflow, but
can be used to log a message.
@param msg an optional message to add to the journal.
@param attributes an [array get] representation of workflow
attribute values to set.
@param assignments an [array get] representation of role assignments
made by this task for this case.
@return journal_id of the newly created journal entry.
@author Lars Pind (lars@pinds.com)
@creation-date 10 July, 2000
} {
if { ![info exists user_id] } {
set user_id [ad_conn user_id]
}
set modifying_ip [ad_conn peeraddr]
db_transaction {
set journal_id [db_exec_plsql begin_task_action {
begin
:1 := workflow_case.begin_task_action(
task_id => :task_id,
action => :action,
action_ip => :modifying_ip,
user_id => :user_id,
msg => :msg);
end;
}]
if { [info exists attributes] } {
array set attr $attributes
foreach attribute_name [array names attr] {
db_exec_plsql set_attribute_value {
begin
workflow_case.set_attribute_value(
journal_id => :journal_id,
attribute_name => :attribute_name,
value => :value
);
end;
} -bind [list journal_id $journal_id \
attribute_name $attribute_name \
value $attr($attribute_name) ]
}
}
if { [info exists assignments] } {
array set asgn $assignments
set case_id [db_string case_id_from_task { select case_id from wf_tasks where task_id = :task_id}]
foreach role_key [array names asgn] {
db_exec_plsql clear_assignments {
begin
workflow_case.clear_manual_assignments(
case_id => :case_id,
role_key => :role_key
);
end;
}
foreach party_id $asgn($role_key) {
db_exec_plsql add_manual_assignment {
begin
workflow_case.add_manual_assignment(
case_id => :case_id,
role_key => :role_key,
party_id => :party_id
);
end;
}
}
}
}
db_exec_plsql end_task_action {
begin
workflow_case.end_task_action(
journal_id => :journal_id,
action => :action,
task_id => :task_id
);
end;
}
}
return $journal_id
}
ad_proc -public wf_message_transition_fire {
task_id
} {
Fires a message transition.
@author Lars Pind (lars@pinds.com)
@creation-date 10 July, 2000
} {
db_exec_plsql transition_fire {
begin
workflow_case.fire_message_transition(
task_id => :task_id
);
end;
}
}
#####
#
# WORKFLOW CASE API
#
#####
ad_proc -public wf_case_new {
-case_id
workflow_key
context_key
object_id
} {
Creates and initializes a case of the given workflow type.
@param case_id for double-click protection, you can optionally supply a
case_id to use here.
@return the case_id of the new case. Throws an error in case of any problems.
@author Lars Pind (lars@pinds.com)
@creation-date 10 July, 2000
} {
set user_id [ad_conn user_id]
set creation_ip [ad_conn peeraddr]
if { ![info exists case_id] } {
set case_id ""
}
set case_id [db_exec_plsql workflow_case_new ""]
db_exec_plsql workflow_case_start_case ""
return $case_id
}
ad_proc -public wf_case_suspend {
{-msg ""}
case_id
} {
Suspends a case
@author Lars Pind (lars@pinds.com)
@creation-date 10 July, 2000
} {
set user_id [ad_conn user_id]
set ip_address [ad_conn peeraddr]
db_exec_plsql case_suspend {
begin
workflow_case.suspend(
case_id => :case_id,
user_id => :user_id,
ip_address => :ip_address,
msg => :msg
);
end;
}
}
ad_proc -public wf_case_resume {
{-msg ""}
case_id
} {
Resumes a suspended case
@author Lars Pind (lars@pinds.com)
@creation-date 10 July, 2000
} {
set user_id [ad_conn user_id]
set ip_address [ad_conn peeraddr]
db_exec_plsql case_resume {
begin
workflow_case.resume(
case_id => :case_id,
user_id => :user_id,
ip_address => :ip_address,
msg => :msg
);
end;
}
}
ad_proc -public wf_case_cancel {
{-msg ""}
case_id
} {
Cancels a case
@author Lars Pind (lars@pinds.com)
@creation-date 10 July, 2000
} {
set user_id [ad_conn user_id]
set ip_address [ad_conn peeraddr]
db_exec_plsql case_cancel {
begin
workflow_case.cancel(
case_id => :case_id,
user_id => :user_id,
ip_address => :ip_address,
msg => :msg
);
end;
}
}
ad_proc -public wf_case_comment {
case_id
msg
} {
Comment on a case
@author Lars Pind (lars@pinds.com)
@creation-date 10 July, 2000
} {
set user_id [ad_conn user_id]
set ip_address [ad_conn peeraddr]
set journal_id [db_exec_plsql case_comment {
begin
:1 := journal_entry.new(
object_id => :case_id,
action => 'comment',
creation_user => :user_id,
creation_ip => :ip_address,
msg => :msg
);
end;
}]
}
ad_proc -public wf_case_add_manual_assignment {
-case_id:required
-role_key:required
-party_id:required
} {
db_exec_plsql add_manual_assignment {
begin
workflow_case.add_manual_assignment(
case_id => :case_id,
role_key => :role_key,
party_id => :party_id
);
end;
}
}
ad_proc -public wf_case_remove_manual_assignment {
-case_id:required
-role_key:required
-party_id:required
} {
db_exec_plsql remove_manual_assignment {
begin
workflow_case.remove_manual_assignment(
case_id => :case_id,
role_key => :role_key,
party_id => :party_id
);
end;
}
}
ad_proc -public wf_case_clear_manual_assignments {
-case_id:required
-role_key:required
} {
db_exec_plsql clear_manual_assignments {
begin
workflow_case.clear_manual_assignments(
case_id => :case_id,
role_key => :role_key
);
end;
}
}
ad_proc -public wf_case_set_manual_assignments {
-case_id:required
-role_key:required
-party_id_list:required
} {
db_transaction {
wf_case_clear_manual_assignments -case_id $case_id -role_key $role_key
foreach party_id $party_id_list {
wf_case_add_manual_assignment -case_id $case_id -role_key $role_key -party_id $party_id
}
}
}
ad_proc -public wf_case_add_task_assignment {
-task_id:required
-party_id:required
-permanent:boolean
} {
set permanent_value [ad_decode $permanent_p 1 "t" 0 "f"]
db_exec_plsql add_task_assignment {
begin
workflow_case.add_task_assignment(
task_id => :task_id,
party_id => :party_id,
permanent_p => :permanent_value
);
end;
}
set case_id [db_string caseid "select case_id from wf_tasks where task_id = :task_id" -default ""]
set transition_key [db_string transitionkey "select transition_key from wf_tasks where task_id = :task_id" -default "undefined"]
set msg "Manual assignment of task `$transition_key` to [acs_object_name $party_id]"
wf_new_journal -case_id $case_id -action "assigned task #$task_id to #$party_id" -action_pretty $msg -message ""
}
ad_proc -public wf_case_remove_task_assignment {
-task_id:required
-party_id:required
-permanent:boolean
} {
set permanent_value [ad_decode $permanent_p 1 "t" 0 "f"]
db_exec_plsql remove_task_assignment {
begin
workflow_case.remove_task_assignment(
task_id => :task_id,
party_id => :party_id,
permanent_p => :permanent_value
);
end;
}
set case_id [db_string caseid "select case_id from wf_tasks where task_id = :task_id" -default ""]
set transition_key [db_string transitionkey "select transition_key from wf_tasks where task_id = :task_id" -default "undefined"]
set msg "Removed manual assignment of task `$transition_key` to [acs_object_name $party_id]"
wf_new_journal -case_id $case_id -action "removed assignment of task #$task_id to #$party_id" -action_pretty $msg -message ""
}
ad_proc -public wf_case_clear_task_assignments {
-task_id:required
-permanent:boolean
} {
set permanent_value [ad_decode $permanent_p 1 "t" 0 "f"]
db_exec_plsql clear_task_assignments {
begin
workflow_case.clear_task_assignments(
task_id => :task_id,
permanent_p => :permanent_value
);
end;
}
}
ad_proc -public wf_case_set_task_assignments {
-task_id:required
-party_id_list:required
-permanent:boolean
} {
db_transaction {
wf_case_clear_task_assignments -task_id $task_id -permanent=$permanent_p
foreach party_id $party_id_list {
wf_case_add_task_assignment -task_id $task_id -party_id $party_id -permanent=$permanent_p
}
}
}
ad_proc -public wf_case_set_case_deadline {
-case_id:required
-transition_key:required
-deadline:required
} {
db_exec_plsql set_case_deadline {
begin
workflow_case.set_case_deadline(
case_id => :case_id,
transition_key => :transition_key,
deadline => :deadline
);
end;
}
}
ad_proc -public wf_case_remove_case_deadline {
-case_id:required
-transition_key:required
} {
db_exec_plsql remove_case_deadline {
begin
workflow_case.remove_case_deadline(
case_id => :case_id,
transition_key => :transition_key
);
end;
}
}
#####
#
# WORKFLOW API
#
#####
ad_proc -public wf_add_place {
-workflow_key:required
-place_key
-place_name:required
{-sort_order ""}
} {
if { ![info exists place_key] } {
set place_key [wf_make_unique -maxlen 100 \
-taken_names [db_list place_keys {select place_key from wf_places where workflow_key = :workflow_key}] \
[wf_name_to_key $place_name]]
}
db_exec_plsql wf_add_place {
begin
workflow.add_place(
workflow_key => :workflow_key,
place_key => :place_key,
place_name => :place_name,
sort_order => :sort_order
);
end;
}
wf_workflow_changed $workflow_key
return $place_key
}
ad_proc -public wf_delete_place {
-workflow_key:required
-place_key:required
} {
db_exec_plsql wf_delete_place {
begin
workflow.delete_place(
workflow_key => :workflow_key,
place_key => :place_key
);
end;
}
wf_workflow_changed $workflow_key
}
ad_proc -public wf_add_role {
-workflow_key:required
-role_key
-role_name:required
{-sort_order ""}
} {
if { ![info exists role_key] } {
set role_key [wf_make_unique -maxlen 100 \
-taken_names [db_list role_keys {select role_key from wf_roles where workflow_key = :workflow_key}] \
[wf_name_to_key $role_name]]
}
db_exec_plsql wf_add_role {
begin
workflow.add_role(
workflow_key => :workflow_key,
role_key => :role_key,
role_name => :role_name,
sort_order => :sort_order
);
end;
}
wf_workflow_changed $workflow_key
return $role_key
}
ad_proc -public wf_move_role_up {
-workflow_key:required
-role_key:required
} {
db_exec_plsql move_role_up {
begin
workflow.move_role_up(
workflow_key => :workflow_key,
role_key => :role_key
);
end;
}
}
ad_proc -public wf_move_role_down {
-workflow_key:required
-role_key:required
} {
db_exec_plsql move_role_down {
begin
workflow.move_role_down(
workflow_key => :workflow_key,
role_key => :role_key
);
end;
}
}
ad_proc -public wf_delete_role {
-workflow_key:required
-role_key:required
} {
db_exec_plsql wf_delete_role {
begin
workflow.delete_role(
workflow_key => :workflow_key,
role_key => :role_key
);
end;
}
wf_workflow_changed $workflow_key
}
ad_proc -public wf_add_transition {
-workflow_key:required
-transition_key
-transition_name:required
{-role_key ""}
{-sort_order ""}
{-trigger_type "user"}
{-instructions ""}
{-estimated_minutes ""}
{-context_key "default"}
} {
if { ![info exists transition_key] } {
set transition_key [wf_make_unique -maxlen 100 \
-taken_names [db_list transition_keys {select transition_key from wf_transitions where workflow_key = :workflow_key}] \
[wf_name_to_key $transition_name]]
}
db_transaction {
db_exec_plsql wf_add_transition {
begin
workflow.add_transition(
workflow_key => :workflow_key,
transition_key => :transition_key,
transition_name => :transition_name,
role_key => :role_key,
sort_order => :sort_order,
trigger_type => :trigger_type
);
end;
}
if { ![empty_string_p $estimated_minutes] || ![empty_string_p $instructions] } {
db_dml estimated_minutes_and_instructions {
insert into wf_context_transition_info
(context_key, workflow_key, transition_key, estimated_minutes, instructions)
values (:context_key, :workflow_key, :transition_key, :estimated_minutes, :instructions)
}
}
}
wf_workflow_changed $workflow_key
return $transition_key
}
ad_proc -public wf_delete_transition {
-workflow_key:required
-transition_key:required
} {
db_exec_plsql wf_delete_transition {
begin
workflow.delete_transition(
workflow_key => :workflow_key,
transition_key => :transition_key
);
end;
}
wf_workflow_changed $workflow_key
}
ad_proc -public wf_add_arc {
-workflow_key:required
-transition_key:required
-place_key:required
-direction:required
{-guard_callback ""}
{-guard_custom_arg ""}
{-guard_description ""}
} {
db_exec_plsql wf_add_arc {
begin
workflow.add_arc(
workflow_key => :workflow_key,
transition_key => :transition_key,
place_key => :place_key,
direction => :direction,
guard_callback => :guard_callback,
guard_custom_arg => :guard_custom_arg,
guard_description => :guard_description
);
end;
}
wf_workflow_changed $workflow_key
}
ad_proc -public wf_add_arc_out {
-workflow_key:required
-from_transition_key:required
-to_place_key:required
{-guard_callback ""}
{-guard_custom_arg ""}
{-guard_description ""}
} {
db_exec_plsql wf_add_arc {
begin
workflow.add_arc(
workflow_key => :workflow_key,
from_transition_key => :from_transition_key,
to_place_key => :to_place_key,
guard_callback => :guard_callback,
guard_custom_arg => :guard_custom_arg,
guard_description => :guard_description
);
end;
}
wf_workflow_changed $workflow_key
}
ad_proc -public wf_add_arc_in {
-workflow_key:required
-from_place_key:required
-to_transition_key:required
} {
db_exec_plsql wf_add_arc {
begin
workflow.add_arc(
workflow_key => :workflow_key,
from_place_key => :from_place_key,
to_transition_key => :to_transition_key
);
end;
}
wf_workflow_changed $workflow_key
}
ad_proc -public wf_delete_arc {
-workflow_key:required
-transition_key:required
-place_key:required
-direction:required
} {
db_exec_plsql wf_delete_arc {
begin
workflow.delete_arc(
workflow_key => :workflow_key,
transition_key => :transition_key,
place_key => :place_key,
direction => :direction
);
end;
}
wf_workflow_changed $workflow_key
}
ad_proc -public wf_add_trans_attribute_map {
-workflow_key:required
-transition_key:required
-attribute_id
-attribute_name
{-sort_order ""}
} {
if { ![info exists attribute_id] && ![info exists attribute_name] } {
return -code error "Either attribute_id or attribute_name must be supplied"
}
if { [info exists attribute_id] } {
db_exec_plsql add_trans_attribute_map_attribute_id {
begin
workflow.add_trans_attribute_map(
workflow_key => :workflow_key,
transition_key => :transition_key,
attribute_id => :attribute_id,
sort_order => :sort_order
);
end;
}
} else {
db_exec_plsql add_trans_attribute_map_attribute_name {
begin
workflow.add_trans_attribute_map(
workflow_key => :workflow_key,
transition_key => :transition_key,
attribute_name => :attribute_name,
sort_order => :sort_order
);
end;
}
}
}
ad_proc -public wf_delete_trans_attribute_map {
-workflow_key:required
-transition_key:required
-attribute_id:required
} {
db_exec_plsql delete_trans_attribute_map {
begin
workflow.delete_trans_attribute_map(
workflow_key => :workflow_key,
transition_key => :transition_key,
attribute_id => :attribute_id
);
end;
}
}
ad_proc -public wf_add_trans_role_assign_map {
-workflow_key:required
-transition_key:required
-assign_role_key:required
} {
db_exec_plsql add_trans_role_assign_map {
begin
workflow.add_trans_role_assign_map(
workflow_key => :workflow_key,
transition_key => :transition_key,
assign_role_key => :assign_role_key
);
end;
}
}
ad_proc -public wf_delete_trans_role_assign_map {
-workflow_key:required
-transition_key:required
-assign_role_key:required
} {
db_exec_plsql delete_trans_role_assign_map {
begin
workflow.delete_trans_role_assign_map(
workflow_key => :workflow_key,
transition_key => :transition_key,
assign_role_key => :assign_role_key
);
end;
}
}
ad_proc -public wf_task_state_pretty {
task_state
} {
Returns a pretty-print version of a task state.
@author Lars Pind (lars@pinds.com)
@creation-date 10 July, 2000
} {
array set pretty {
enabled Waiting
started Active
canceled Canceled
finished Finished
overridden Overriden
}
return $pretty($task_state)
}
ad_proc -public wf_task_actions {
task_state
} {
Returns a list of the possible actions given the task state.
@author Lars Pind (lars@pinds.com)
@creation-date 10 July, 2000
} {
switch -- $task_state {
enabled {
return [list start]
}
started {
return [list finish cancel]
}
default {
return [list]
}
}
}
ad_proc -public wf_action_pretty {
action
} {
Returns the pretty version of a task action.
@author Lars Pind (lars@pinds.com)
@creation-date 10 July, 2000
} {
array set pretty {
start Start
finish Finish
cancel Cancel
comment Comment
}
return $pretty($action)
}
ad_proc -public wf_simple_workflow_p {
workflow_key
} {
Returns whether the workflow is "almost linear" or not. Roughly,
"almost linear" means whether we can represent it graphically within
the confines of HTML. Currently that means only simple iteration is
permitted.
@author Kevin Scaldeferri (kevin@theory.caltech.edu)
@creation-date 10 July, 2000
} {
return [ad_decode [db_exec_plsql simple_workflow "begin :1 := workflow.simple_p(:workflow_key); end;"] t 1 f 0 0]
}
#####
#
# EXPORT
#
#####
ad_proc wf_export_workflow {
{-context_key "default"}
-new_workflow_key
-new_table_name
-new_workflow_pretty_name
-new_workflow_pretty_plural
workflow_key
} {
Generates a SQL script that can re-create this process in another installation.
} {
if { ![info exists new_workflow_key] } {
set new_workflow_key $workflow_key
}
#####
#
# Workflow Object Type
#
#####
db_1row workflow_info {
select wf.description,
ot.pretty_name,
ot.pretty_plural,
ot.table_name
from wf_workflows wf,
acs_object_types ot
where wf.workflow_key = :workflow_key
and ot.object_type = wf.workflow_key
}
if { ![info exists new_table_name] } {
set new_table_name $table_name
}
if { ![info exists new_workflow_pretty_name] } {
set new_workflow_pretty_name $pretty_name
}
if { ![info exists new_workflow_pretty_plural] } {
set new_workflow_pretty_plural $pretty_plural
}
append sql "
/*
* Business Process Definition: $pretty_name ($new_workflow_key[ad_decode $workflow_key $new_workflow_key "" ", copy of $workflow_key"])
*
* Auto-generated by ACS Workflow Export, version 4.3
*
* Context: $context_key
*/
/*
* Cases table
*/
create table $new_table_name (
case_id integer primary key
references wf_cases on delete cascade
);
/*
* Declare the object type
*/
[db_map declare_object_type]
"
#####
#
# Places
#
#####
append sql "
/*****
* Places
*****/
"
db_foreach places {
select place_key,
place_name,
sort_order
from wf_places
where workflow_key = :workflow_key
order by sort_order asc
} {
append sql "[db_map add_place]"
}
#####
#
# Roles
#
#####
append sql "
/*****
* Roles
*****/
"
db_foreach roles {
select role_key,
role_name,
sort_order
from wf_roles
where workflow_key = :workflow_key
} {
append sql "[db_map add_role]"
}
#####
#
# Transitions
#
#####
append sql "
/*****
* Transitions
*****/
"
db_foreach transitions {
select transition_key,
transition_name,
role_key,
sort_order,
trigger_type
from wf_transitions
where workflow_key = :workflow_key
order by sort_order asc
} {
append sql "[db_map add_transition]"
}
#####
#
# Arcs
#
#####
append sql "
/*****
* Arcs
*****/
"
db_foreach arcs {
select transition_key,
place_key,
direction,
guard_callback,
guard_custom_arg,
guard_description
from wf_arcs
where workflow_key = :workflow_key
order by transition_key asc
} {
append sql "[db_map add_arc]"
}
#####
#
# Attributes
#
#####
append sql "
/*****
* Attributes
*****/
"
db_foreach attributes {
select attribute_id,
attribute_name,
datatype,
pretty_name,
default_value
from acs_attributes
where object_type = :workflow_key
} {
append sql [db_map create_attribute]
db_foreach transition_attribute_map {
select transition_key,
sort_order
from wf_transition_attribute_map
where workflow_key = :workflow_key
and attribute_id = :attribute_id
} {
append sql [db_map add_trans_attribute_map]
}
}
#####
#
# Transition-role-assignment map
#
#####
append sql "
/*****
* Transition-role-assignment-map
*****/
"
db_foreach transition_role_assign_map {
select transition_key,
assign_role_key
from wf_transition_role_assign_map
where workflow_key = :workflow_key
order by transition_key
} {
append sql [db_map add_trans_role_assign_map]
}
#####
#
# Context-Transition info
#
#####
append sql "
/*
* Context/Transition info
* (for context = $context_key)
*/
"
db_foreach context_transition_info {
select transition_key,
estimated_minutes,
instructions,
enable_callback,
enable_custom_arg,
fire_callback,
fire_custom_arg,
time_callback,
time_custom_arg,
deadline_callback,
deadline_custom_arg,
deadline_attribute_name,
hold_timeout_callback,
hold_timeout_custom_arg,
notification_callback,
notification_custom_arg,
unassigned_callback,
unassigned_custom_arg
from wf_context_transition_info
where workflow_key = :workflow_key
and context_key = :context_key
} {
append sql "insert into wf_context_transition_info
(context_key,
workflow_key,
transition_key,
estimated_minutes,
instructions,
enable_callback,
enable_custom_arg,
fire_callback,
fire_custom_arg,
time_callback,
time_custom_arg,
deadline_callback,
deadline_custom_arg,
deadline_attribute_name,
hold_timeout_callback,
hold_timeout_custom_arg,
notification_callback,
notification_custom_arg,
unassigned_callback,
unassigned_custom_arg)
values
('[db_quote $context_key]',
'[db_quote $new_workflow_key]',
'[db_quote $transition_key]',
[ad_decode $estimated_minutes "" "null" $estimated_minutes],
'[db_quote $instructions]',
'[db_quote $enable_callback]',
'[db_quote $enable_custom_arg]',
'[db_quote $fire_callback]',
'[db_quote $fire_custom_arg]',
'[db_quote $time_callback]',
'[db_quote $time_custom_arg]',
'[db_quote $deadline_callback]',
'[db_quote $deadline_custom_arg]',
'[db_quote $deadline_attribute_name]',
'[db_quote $hold_timeout_callback]',
'[db_quote $hold_timeout_custom_arg]',
'[db_quote $notification_callback]',
'[db_quote $notification_custom_arg]',
'[db_quote $unassigned_callback]',
'[db_quote $unassigned_custom_arg]');
"
}
#####
#
# Context-Role info
#
#####
append sql "
/*
* Context/Role info
* (for context = $context_key)
*/
"
db_foreach context_role_info {
select role_key,
assignment_callback,
assignment_custom_arg
from wf_context_role_info
where workflow_key = :workflow_key
and context_key = :context_key
} {
append sql "insert into wf_context_role_info
(context_key,
workflow_key,
role_key,
assignment_callback,
assignment_custom_arg)
values
('[db_quote $context_key]',
'[db_quote $new_workflow_key]',
'[db_quote $role_key]',
'[db_quote $assignment_callback]',
'[db_quote $assignment_custom_arg]');
"
}
#####
#
# Context Task Panels
#
#####
append sql "
/*
* Context Task Panels
* (for context = $context_key)
*/
"
db_foreach context_task_panels {
select transition_key,
sort_order,
header,
template_url,
overrides_action_p,
overrides_both_panels_p,
only_display_when_started_p
from wf_context_task_panels
where context_key = :context_key
and workflow_key = :workflow_key
order by transition_key asc, sort_order asc
} {
append sql "insert into wf_context_task_panels
(context_key,
workflow_key,
transition_key,
sort_order,
header,
template_url,
overrides_action_p,
overrides_both_panels_p,
only_display_when_started_p)
values
('[db_quote $context_key]',
'[db_quote $new_workflow_key]',
'[db_quote $transition_key]',
[ad_decode $sort_order "" "null" $sort_order],
'[db_quote $header]',
'[db_quote $template_url]',
'[db_quote $overrides_action_p]',
'[db_quote $overrides_both_panels_p]',
'[db_quote $only_display_when_started_p]');
"
}
append sql "
commit;
"
return $sql
}
ad_proc wf_split_query_url_to_arg_spec { query_url } {
Splits a URL including query arguments (e.g., /foo/bar?baz=greble&yank=zazz)
up into a list of lists of name/value pairs, that can be passed as an argument
to export_vars.
Useful for pages that receive a return_url argument, but wants to
execute the actual return using a form submit button.
@author Lars Pind (lars@pinds.com)
@creation-date Feb 26, 2001
} {
set arg_spec {}
foreach arg [split [lindex [split $query_url "?"] 1] "&"] {
set argv [split $arg "="]
set name [ns_urldecode [lindex $argv 0]]
set value [ns_urldecode [lindex $argv 1]]
lappend arg_spec [list $name $value]
}
return $arg_spec
}
ad_proc wf_sweep_time_events {} {
Sweep timed transitions and hold timeouts. This was originally done with Oracle
but has been pulled out here so it will work with any RDBMS.
@author Don Baccus (dhogaza@pacifier.com)
} {
ns_log Notice "workflow-case: sweeping timed transitions"
db_exec_plsql sweep_timed_transitions ""
ns_log Notice "workflow-case: sweeping hold timeout"
db_exec_plsql sweep_hold_timeout ""
}
ad_proc -public wf_new_journal {
-case_id:required
-action:required
-action_pretty:required
-message:required
} {
Creates a new journal entry that can be passed to PL/SQL routines
} {
set user_id 0
set peer_ip "0.0.0.0"
catch {
set user_id [ad_conn user_id]
set peer_ip [ad_conn peeraddr]
}
set jid [db_string new_journal "
select journal_entry__new (
null,
:case_id,
:action,
:action_pretty,
now(),
:user_id,
:peer_ip,
:message
)
"]
return $jid
}
ad_proc wf_sweep_message_transition_tcl {} {
Sweep those message transitions that have a TCL callback
and advance the transitions.
The procedure is designed to allow WF transitions to
trigger TCL procedures, which is usually impossible,
because the entire WF works on the PlPg/SQL level.
We dont want to make changes in the WF data model right
now, so we're looking at the "enabled" callbacls of message
transitions and check if the actual PlPg/SQL call is empty,
but if there is an argument and execute this argument as
a TCL call. Ugly, but may work...
@author Frank Bergmann (frank.bergmann@project-open.com)
} {
ns_log Notice "workflow-case: sweeping message transition TCL"
set user_id [ad_conn user_id]
set ip_address [ad_conn peeraddr]
set sweep_sql "
select
ta.*,
tr.*,
ca.object_id,
ti.enable_custom_arg as tcl_call
from
wf_tasks ta,
wf_cases ca,
wf_transitions tr,
wf_context_transition_info ti
where
ta.workflow_key = tr.workflow_key
and ta.transition_key = tr.transition_key
and ta.workflow_key = ti.workflow_key
and ta.transition_key = ti.transition_key
and ta.case_id = ca.case_id
and
(ti.enable_callback = '' OR ti.enable_callback is NULL) and
ta.state = 'enabled'
and tr.trigger_type = 'message'
"
set found_transition_p 1
while {$found_transition_p} {
# By default: Just do this once...
set found_transition_p 0
# Execute the TCL commands and initiate events.
db_foreach sweep_message_transition_tcl $sweep_sql {
# Found a transition to sweep - loop again,
# because there could be new tasks open after executing $tcl_call
set found_transition_p 1
set error_msg "successful"
ns_log Notice "wf_sweep_message_transition_tcl: executing '$tcl_call' ..."
if {[catch {
eval $tcl_call
ns_log Notice "wf_sweep_message_transition_tcl: ... successful"
} errmsg]} {
ns_log Error "wf_sweep_message_transition_tcl: ... error: $errmsg"
set error_msg $errmsg
# Send out a notification to the admin that the transition gave an error
set message "workflow: $workflow_key\ntransition: $transition_key\ncase_id: $case_id\nerror_msg: \n$errmsg"
im_send_alert_to_system_owner "Error in Workflow TCL Callback: $tcl_call" $message
}
wf_new_journal -case_id $case_id -action "task $task_id tcl enable" -action_pretty "Enable TCL task $task_id: '$tcl_call'" -message "TCL call '$tcl_call' returned: '$errmsg'"
# Advance the message transition in either case (error or not)
# So a failing TCL call will not block the entire workflow
# leading to ugly hanging or unassigned transitions.
wf_message_transition_fire $task_id
}
}
}
acs-workflow-master/tcl/workflow-procs.xql 0000664 0000000 0000000 00000021556 14575002472 0021312 0 ustar 00root root 0000000 0000000
select r.role_key,
r.role_name,
'' as assignment_widget
from wf_tasks t, wf_transition_role_assign_map tram, wf_roles r
where t.task_id = :task_id
and tram.workflow_key = t.workflow_key and tram.transition_key = t.transition_key
and r.workflow_key = tram.workflow_key and r.role_key = tram.assign_role_key
order by r.sort_order
select tp.header,
tp.template_url
from wf_context_task_panels tp,
wf_cases c,
wf_tasks t
where t.task_id = :task_id
and c.case_id = t.case_id
and tp.context_key = c.context_key
and tp.workflow_key = c.workflow_key
and tp.transition_key = t.transition_key
and tp.overrides_action_p = 't'
and (tp.only_display_when_started_p = 'f' or (t.state = 'started' and t.holding_user = :user_id))
order by tp.overrides_action_p, tp.sort_order
select tp.header,
tp.template_url
from wf_context_task_panels tp,
wf_cases c,
wf_tasks t
where t.task_id = :task_id
and c.case_id = t.case_id
and tp.context_key = c.context_key
and tp.workflow_key = c.workflow_key
and tp.transition_key = t.transition_key
and (tp.only_display_when_started_p = 'f' or (t.state = 'started' and t.holding_user = :user_id))
order by tp.overrides_action_p, tp.sort_order
select count(*) from wf_user_tasks where task_id = :task_id and user_id = :user_id
select a.attribute_name as name,
a.pretty_name,
a.datatype,
v.attr_value as value
from wf_attribute_value_audit v, acs_attributes a
where v.journal_id = :journal_id
and a.attribute_id = v.attribute_id
select t.pretty_name,
w.description
from wf_workflows w, acs_object_types t
where w.workflow_key = :workflow_key
and t.object_type = w.workflow_key
select transition_key, transition_name, sort_order
from wf_transitions
where workflow_key = :workflow_key
and trigger_type = 'user'
order by sort_order asc
select a.attribute_name as name,
a.pretty_name,
a.datatype,
v.attr_value as value
from wf_attribute_value_audit v, acs_attributes a
where v.journal_id = :journal_id
and a.attribute_id = v.attribute_id
select case_id from wf_tasks where task_id = :task_id
select place_key from wf_places where workflow_key = :workflow_key
select role_key from wf_roles where workflow_key = :workflow_key
select transition_key from wf_transitions where workflow_key = :workflow_key
insert into wf_context_transition_info
(context_key, workflow_key, transition_key, estimated_minutes, instructions)
values (:context_key, :workflow_key, :transition_key, :estimated_minutes, :instructions)
select wf.description,
ot.pretty_name,
ot.pretty_plural,
ot.table_name
from wf_workflows wf,
acs_object_types ot
where wf.workflow_key = :workflow_key
and ot.object_type = wf.workflow_key
select place_key,
place_name,
sort_order
from wf_places
where workflow_key = :workflow_key
order by sort_order asc
select role_key,
role_name,
sort_order
from wf_roles
where workflow_key = :workflow_key
select transition_key, transition_name, sort_order
from wf_transitions
where workflow_key = :workflow_key
and trigger_type = 'user'
order by sort_order asc
select transition_key,
place_key,
direction,
guard_callback,
guard_custom_arg,
guard_description
from wf_arcs
where workflow_key = :workflow_key
order by transition_key asc
select a.attribute_name as name,
a.pretty_name,
a.datatype,
v.attr_value as value
from wf_attribute_value_audit v, acs_attributes a
where v.journal_id = :journal_id
and a.attribute_id = v.attribute_id
select transition_key,
sort_order
from wf_transition_attribute_map
where workflow_key = :workflow_key
and attribute_id = :attribute_id
select transition_key,
assign_role_key
from wf_transition_role_assign_map
where workflow_key = :workflow_key
order by transition_key
select transition_key,
estimated_minutes,
instructions,
enable_callback,
enable_custom_arg,
fire_callback,
fire_custom_arg,
time_callback,
time_custom_arg,
deadline_callback,
deadline_custom_arg,
deadline_attribute_name,
hold_timeout_callback,
hold_timeout_custom_arg,
notification_callback,
notification_custom_arg,
unassigned_callback,
unassigned_custom_arg
from wf_context_transition_info
where workflow_key = :workflow_key
and context_key = :context_key
select role_key,
assignment_callback,
assignment_custom_arg
from wf_context_role_info
where workflow_key = :workflow_key
and context_key = :context_key
select transition_key,
sort_order,
header,
template_url,
overrides_action_p,
overrides_both_panels_p,
only_display_when_started_p
from wf_context_task_panels
where context_key = :context_key
and workflow_key = :workflow_key
order by transition_key asc, sort_order asc
acs-workflow-master/www/ 0000775 0000000 0000000 00000000000 14575002472 0015617 5 ustar 00root root 0000000 0000000 acs-workflow-master/www/active-tasks-oracle.xql 0000664 0000000 0000000 00000002333 14575002472 0022207 0 ustar 00root root 0000000 0000000
oracle8.1.6
select t.task_id,
t.transition_key,
t.state,
t.case_id,
tr.transition_name,
to_char(t.enabled_date, :date_format) as enabled_date_pretty,
to_char(t.started_date, :date_format) as started_date_pretty,
to_char(t.deadline, :date_format) as deadline_pretty,
p.party_id as assignee_party_id,
p.email as assignee_email,
acs_object.name(p.party_id) as assignee_name,
'' as assignee_url,
assignee_o.object_type as assignee_object_type,
'' as reassign_url
from wf_tasks t, wf_transitions tr, wf_task_assignments tasgn, parties p, acs_objects assignee_o
where t.case_id = :case_id
and t.state in ('enabled', 'started')
and tr.workflow_key = t.workflow_key
and tr.transition_key = t.transition_key
and tasgn.task_id (+) = t.task_id
and p.party_id (+) = tasgn.party_id
and assignee_o.object_id (+) = p.party_id
order by t.enabled_date desc
acs-workflow-master/www/active-tasks-postgresql.xql 0000664 0000000 0000000 00000002523 14575002472 0023146 0 ustar 00root root 0000000 0000000
postgresql7.1
select t.task_id,
t.transition_key,
t.state,
t.case_id,
t.holding_user,
acs_object__name(t.holding_user) as holding_user_name,
tr.transition_name,
to_char(t.enabled_date, :date_format) as enabled_date_pretty,
to_char(t.started_date, :date_format) as started_date_pretty,
to_char(t.deadline, :date_format) as deadline_pretty,
p.party_id as assignee_party_id,
p.email as assignee_email,
acs_object__name(p.party_id) as assignee_name,
'' as assignee_url,
assignee_o.object_type as assignee_object_type,
'' as reassign_url
from (((wf_tasks t LEFT OUTER JOIN wf_task_assignments tasgn
ON (t.task_id = tasgn.task_id)) LEFT OUTER JOIN parties p
ON (tasgn.party_id = p.party_id)) LEFT OUTER JOIN acs_objects assignee_o
ON (p.party_id = assignee_o.object_id)),
wf_transitions tr
where t.case_id = :case_id
and t.state in ('enabled', 'started')
and tr.workflow_key = t.workflow_key
and tr.transition_key = t.transition_key
order by t.enabled_date desc
acs-workflow-master/www/active-tasks.adp 0000664 0000000 0000000 00000004357 14575002472 0020714 0 ustar 00root root 0000000 0000000
(#acs-workflow.add_attribute#)
acs-workflow-master/www/admin/attributes-table.tcl 0000664 0000000 0000000 00000001714 14575002472 0022671 0 ustar 00root root 0000000 0000000 #
# Attributes table.
#
# Input:
# workflow_key
# return_url (optional)
# modifiable_p (optional)
#
# Data sources:
# attributes
# add_url
#
# Author: Lars Pind (lars@pinds.com)
# Creation-date: Feb 26, 2001
# Cvs-id: $Id$
#
if { ![info exists modifiable_p] } {
set modifiable_p 1
}
db_multirow attributes attributes {
select a.attribute_id,
a.sort_order,
a.attribute_name,
a.pretty_name,
a.datatype,
'' as delete_url,
(select count(*) from wf_transition_attribute_map m
where m.workflow_key = a.object_type
and m.attribute_id = a.attribute_id) as used_p
from acs_attributes a
where a.object_type = :workflow_key
order by sort_order
} {
if { $modifiable_p } {
set delete_url "attribute-delete?[export_vars -url {workflow_key attribute_id return_url}]"
}
}
set add_url "attribute-add?[export_vars -url {workflow_key return_url}]"
acs-workflow-master/www/admin/attributes-table.xql 0000664 0000000 0000000 00000001072 14575002472 0022710 0 ustar 00root root 0000000 0000000
select a.attribute_id,
a.sort_order,
a.attribute_name,
a.pretty_name,
a.datatype,
'' as delete_url,
(select count(*) from wf_transition_attribute_map m
where m.workflow_key = a.object_type
and m.attribute_id = a.attribute_id) as used_p
from acs_attributes a
where a.object_type = :workflow_key
order by sort_order
acs-workflow-master/www/admin/attributes.adp 0000664 0000000 0000000 00000001131 14575002472 0021557 0 ustar 00root root 0000000 0000000 #acs-workflow.lt_Attributes_for_workfl#@context;noquote@
acs-workflow-master/www/admin/attributes.tcl 0000664 0000000 0000000 00000001325 14575002472 0021602 0 ustar 00root root 0000000 0000000 ad_page_contract {
Manage workflow attributes.
@author Lars Pind (lars@pinds.com)
@creation-date December 15, 2000
@cvs-id $Id$
} {
workflow_key
} -validate {
workflow_exists -requires {workflow_key} {
if ![db_string workflow_exists "
select 1 from wf_workflows
where workflow_key = :workflow_key"] {
ad_complain "You seem to have specified a nonexistent workflow."
}
}
} -properties {
workflow_key
context
}
db_1row workflow_name {
select ot.pretty_name as workflow_name
from acs_object_types ot
where ot.object_type = :workflow_key
}
set context [list [list "workflow?[export_vars -url { workflow_key}]" "$workflow_name"] "Attributes"]
ad_return_template
acs-workflow-master/www/admin/attributes.xql 0000664 0000000 0000000 00000000654 14575002472 0021630 0 ustar 00root root 0000000 0000000
select 1 from wf_workflows
where workflow_key = :workflow_key
select ot.pretty_name as workflow_name
from acs_object_types ot
where ot.object_type = :workflow_key
acs-workflow-master/www/admin/case-debug-oracle.xql 0000664 0000000 0000000 00000002306 14575002472 0022700 0 ustar 00root root 0000000 0000000
oracle8.1.6
select case_id, acs_object.name(object_id) as object_name, state as state from wf_cases where case_id = :case_id
select a.attribute_name as name, acs_object.get_attribute(c.case_id, a.attribute_name) as value
from acs_attributes a, wf_cases c
where a.object_type = c.workflow_key
and c.case_id = :case_id
select token_id, place_key, case_id, state, locked_task_id,
to_char(produced_date, 'YYYY-MM-DD HH24:MI:SS') as produced_date_pretty,
to_char(locked_date, 'YYYY-MM-DD HH24:MI:SS') as locked_date_pretty,
to_char(consumed_date, 'YYYY-MM-DD HH24:MI:SS') as consumed_date_pretty,
to_char(canceled_date, 'YYYY-MM-DD HH24:MI:SS') as canceled_date_pretty
from wf_tokens
where case_id = :case_id
and state in ('consumed', 'canceled')
acs-workflow-master/www/admin/case-debug-postgresql.xql 0000664 0000000 0000000 00000002312 14575002472 0023633 0 ustar 00root root 0000000 0000000
postgresql7.1
select case_id, acs_object__name(object_id) as object_name, state as state from wf_cases where case_id = :case_id
select a.attribute_name as name, acs_object__get_attribute(c.case_id, a.attribute_name) as value
from acs_attributes a, wf_cases c
where a.object_type = c.workflow_key
and c.case_id = :case_id
select token_id, place_key, case_id, state, locked_task_id,
to_char(produced_date, 'YYYY-MM-DD HH24:MI:SS') as produced_date_pretty,
to_char(locked_date, 'YYYY-MM-DD HH24:MI:SS') as locked_date_pretty,
to_char(consumed_date, 'YYYY-MM-DD HH24:MI:SS') as consumed_date_pretty,
to_char(canceled_date, 'YYYY-MM-DD HH24:MI:SS') as canceled_date_pretty
from wf_tokens
where case_id = :case_id
and state in ('consumed', 'canceled')
acs-workflow-master/www/admin/case-debug.adp 0000664 0000000 0000000 00000004775 14575002472 0021411 0 ustar 00root root 0000000 0000000 #acs-workflow.lt_Case_caseobject_namen#@context;noquote@
acs-workflow-master/www/admin/case-debug.tcl 0000664 0000000 0000000 00000003643 14575002472 0021420 0 ustar 00root root 0000000 0000000 ad_page_contract {
Displays information about a case.
@author Lars Pind (lars@pinds.com)
@creation-date 18 August 2000
@cvs-id $Id$
} {
case_id:integer,notnull
} -properties {
context
case:onerow
tasks:multirow
attributes:multirow
live_tokens:multirow
dead_tokens:multirow
enabled_transitions:multirow
}
db_1row case_info {
select case_id, acs_object.name(object_id) as object_name, state as state from wf_cases where case_id = :case_id
} -column_array case
set context [list "Case $case(object_name)"]
db_multirow tasks tasks {
select task_id, transition_key, state, case_id
from wf_tasks
where case_id = :case_id
order by decode(state, 'started', 1, 'enabled', 2, 'finished', 3, 4)
}
db_multirow attributes attributes {
select a.attribute_name as name, acs_object.get_attribute(c.case_id, a.attribute_name) as value
from acs_attributes a, wf_cases c
where a.object_type = c.workflow_key
and c.case_id = :case_id
}
db_multirow live_tokens live_tokens {
select token_id, place_key, case_id, state, locked_task_id
from wf_tokens
where case_id = :case_id
and state in ('free', 'locked')
}
db_multirow dead_tokens dead_tokens {
select token_id, place_key, case_id, state, locked_task_id,
to_char(produced_date, 'YYYY-MM-DD HH24:MI:SS') as produced_date_pretty,
to_char(locked_date, 'YYYY-MM-DD HH24:MI:SS') as locked_date_pretty,
to_char(consumed_date, 'YYYY-MM-DD HH24:MI:SS') as consumed_date_pretty,
to_char(canceled_date, 'YYYY-MM-DD HH24:MI:SS') as canceled_date_pretty
from wf_tokens
where case_id = :case_id
and state in ('consumed', 'canceled')
}
db_multirow enabled_transitions enabled_transitions {
select case_id, transition_key, transition_name, trigger_type
from wf_enabled_transitions
where case_id = :case_id
}
ad_return_template acs-workflow-master/www/admin/case-debug.xql 0000664 0000000 0000000 00000001510 14575002472 0021431 0 ustar 00root root 0000000 0000000
select task_id, transition_key, state, case_id
from wf_tasks
where case_id = :case_id
order by case when state = 'started' then 1 when state = 'enabled' then 2 when state = 'finished' then 3 else 4 end
select token_id, place_key, case_id, state, locked_task_id
from wf_tokens
where case_id = :case_id
and state in ('free', 'locked')
select case_id, transition_key, transition_name, trigger_type
from wf_enabled_transitions
where case_id = :case_id
acs-workflow-master/www/admin/cases-oracle.xql 0000664 0000000 0000000 00000002055 14575002472 0022000 0 ustar 00root root 0000000 0000000
oracle8.1.6
select c.case_id,
o.object_type,
ot.pretty_name as object_type_pretty,
acs_object.name(c.object_id) as object_name,
c.state,
jeo.creation_date as started_date,
to_char(jeo.creation_date, 'Mon fmDDfm, YYYY HH24:MI:SS') as started_date_pretty,
round(sysdate - jeo.creation_date) as age
from wf_cases c,
acs_objects o,
acs_object_types ot,
journal_entries je,
acs_objects jeo
where c.workflow_key = '[db_quote $workflow_key]'
and o.object_id = c.object_id
and ot.object_type = o.object_type
and je.object_id = c.case_id
and je.action = 'case start'
and jeo.object_id = je.journal_id
[ad_dimensional_sql $dimensional_list where and]
[ad_order_by_from_sort_spec $orderby $table_def]
acs-workflow-master/www/admin/cases-postgresql.xql 0000664 0000000 0000000 00000002047 14575002472 0022737 0 ustar 00root root 0000000 0000000
postgresql7.1
select c.case_id,
o.object_type,
ot.pretty_name as object_type_pretty,
acs_object__name(c.object_id) as object_name,
c.state,
jeo.creation_date as started_date,
to_char(jeo.creation_date, 'Mon fmDDfm, YYYY HH24:MI:SS') as started_date_pretty,
now() - jeo.creation_date as age
from wf_cases c,
acs_objects o,
acs_object_types ot,
journal_entries je,
acs_objects jeo
where c.workflow_key = '[db_quote $workflow_key]'
and o.object_id = c.object_id
and ot.object_type = o.object_type
and je.object_id = c.case_id
and je.action = 'case start'
and jeo.object_id = je.journal_id
[ad_dimensional_sql $dimensional_list where and]
[ad_order_by_from_sort_spec $orderby $table_def]
acs-workflow-master/www/admin/cases.adp 0000664 0000000 0000000 00000000316 14575002472 0020473 0 ustar 00root root 0000000 0000000 #acs-workflow.lt_workflow_namenoquote_#@context;noquote@
@dimensional_html;noquote@
@table_html;noquote@
acs-workflow-master/www/admin/cases.tcl 0000664 0000000 0000000 00000006426 14575002472 0020521 0 ustar 00root root 0000000 0000000 ad_page_contract {
View active cases.
@author Lars Pind (lars@pinds.com)
@creation-date 25 September 2000
@cvs-id $Id$
} {
workflow_key:notnull,trim
{orderby "started_date_pretty"}
} -validate {
workflow_exists -requires {workflow_key} {
if ![db_string workflow_exists "
select 1 from wf_workflows
where workflow_key = :workflow_key"] {
ad_complain "You seem to have specified a nonexistent workflow."
}
}
} -properties {
context
workflow_name
cases:multirow
dimensional_html
table_html
}
db_1row workflow_name {
select pretty_name as workflow_name
from acs_object_types
where object_type = :workflow_key
}
set workflow_name [ad_quotehtml $workflow_name]
set context [list [list "workflow?[export_vars -url { workflow_key}]" "$workflow_name"] "Cases"]
#
# Use ad_table here
#
set dimensional_list {
{
state "State" all {
{ created "Created" { where "c.state = 'created'" } }
{ active "Active" { where "c.state = 'active'" } }
{ suspended "Suspended" { where "c.state = 'suspended'" } }
{ canceled "Canceled" { where "c.state = 'canceled'" } }
{ finished "Finished" { where "c.state = 'finished'" } }
{ all "-- All --" {} }
}
}
}
set transitions_dim [list]
db_foreach transitions {
select transition_key, transition_name
from wf_transitions
where workflow_key = :workflow_key
order by transition_name
} {
lappend transitions_dim [list $transition_key $transition_name [list where "exists (select 1 from wf_tasks ta
where ta.workflow_key = '[db_quote $workflow_key]'
and ta.transition_key = '[db_quote $transition_key]'
and ta.state = 'started'
and ta.case_id = c.case_id)"]]
}
lappend transitions_dim [list all "-- All --" {}]
set places_dim [list]
db_foreach places {
select place_key, place_name
from wf_places
where workflow_key = :workflow_key
order by place_name
} {
lappend places_dim [list $place_key $place_name [list where "exists (select 1 from wf_tokens tok
where tok.workflow_key = '[db_quote $workflow_key]'
and tok.place_key = '[db_quote $place_key]'
and tok.state = 'free'
and tok.case_id = c.case_id)"]]
}
lappend places_dim [list all "-- All --" {}]
lappend dimensional_list [list transition_key "Task" all $transitions_dim]
lappend dimensional_list [list place_key "Place" all $places_dim]
set missing_text "No cases match criteria."
set dimensional_html [ad_dimensional $dimensional_list "" "" "select"]
# The above does obviously not render very nicely.
# Some day we should really implement the option on ad_dimensional to render as