Technical Design Document Sample/Template

advertisement
<Project Name>
Technical Design Document
<Company Banner>
Version 1.0
Document Control
Version
Author
Issue Reason
2
Date
Table of Contents
Section 1 – Statement of Purpose __________________________________________ 5
Purpose ____________________________________________________________________ 5
Overview ___________________________________________________________________ 5
Section 2 - System Topology ______________________________________________ 6
Overview ___________________________________________________________________ 6
Logical View ________________________________________________________________ 6
Physical View _______________________________________________________________ 7
Section 3 - System Level Sequence Diagram _________________________________ 8
Overview ___________________________________________________________________ 8
Description of Sequence Diagram_______________________________________________ 9
Section 4 – <Product name> Interface Definitions ___________________________ 10
Overview __________________________________________________________________ 10
CTI Object Info Functions ___________________________________________________ 10
Function Code 1: getCallDefaultInfo _________________________________________________ 10
Administrative Functions ____________________________________________________ 11
Function Code 98: echo ____________________________________________________________ 11
Function Code 99: stop ____________________________________________________________ 11
Get Reply Function _________________________________________________________ 12
Function Code 0: getReply _________________________________________________________ 12
Section 5 – <Product Name> Functionality Mapping to <Third party SDK> ______ 13
Overview __________________________________________________________________ 13
Initialization _______________________________________________________________ 13
getCallDefaultInfo __________________________________________________________ 13
getCallInfo ________________________________________________________________ 13
Section 6 – <Product name> Process Flow Diagrams _________________________ 14
Overview __________________________________________________________________ 14
Threads of execution in the ivrpgd _____________________________________________ 14
Main Thread Flow of Execution diagram _______________________________________ 15
Request Processor Thread Flow of Execution diagram _____________________________ 16
Section 7 – <Product name> Class Descriptions and Diagram __________________ 17
Overview __________________________________________________________________ 17
Class Descriptions __________________________________________________________ 17
TuposDmIPGD __________________________________________________________________ 17
Class Diagram-Tupos Framework Related Classes ________________________________ 18
Class Diagram - 3CS SDK Related Classes ______________________________________ 19
3
Section 8 – <Product name> Collaboration Diagrams ________________________ 20
Overview __________________________________________________________________ 20
Queuing Client Requests _____________________________________________________ 20
Handling Client Reply Requests _______________________________________________ 21
Section 9 – <Product name> Configuration Options __________________________ 22
Overview __________________________________________________________________ 22
Configuration Options _______________________________________________________ 22
Section 10 - Sign-off Sheet ______________________________________________ 23
Purpose ___________________________________________________________________ 23
Directions _________________________________________________________________ 23
Contact Information ________________________________________________________ 23
Sign-off ___________________________________________________________________ 23
4
Section 1 – Statement of Purpose
Purpose
The Technical Design Document is the artifact that specifies the details of the designed solution. When
considering a black-box engineering approach, the Technical Design Document describes the details of
how the black box works.
For Object Oriented software design, this includes UML diagrams (e.g., Class Diagrams, Object Interaction
Diagrams, etc.) as well as detailed descriptions of the classes, procedures, etc. There is typically no lower
level artifact, other than the source code itself.
This document should always be drafted in some form or another, however, it is rarely given to the
customer. The CCS software development team reserves the right to make all decisions regarding software
design and implementation.
Overview
[Describe the purpose of this document here. Mention the name of the product, the problem it is trying to
solve and the name of the customer.]
5
Section 2 - System Topology
[This section should provide a static view of the entire system for this solution. It should identify at a
system level what components will be needed. It should provide a logical and physical view of the solution.
]
Overview
[Provide and overview of the system topology. See example below]
This section provides a static view of the entire system for this solution. This section identifies at a system
level what components will be needed. This section also identifies communication between components.
Logical View
[Describe the logical topology of the solution. This includes the various software components in the
solution and their relationships to other software components. Provide a picture as shown in the following
example and describe the picture in this section.]
3CS/IVR Premise Gateway Logical Topology
Spectrum
ACD
Voice
3CS Linkage
3CS
Infrastructure
Voice
ivrpgd:0
3CS
SDK
IVR 0
Thin Client
tuposd
ivrpgd:1
3CS
SDK
IVR 1
Thin Client
Legend:
Process Parent/Child Relationship
Voice
Data Link
Figure 2-1
6
Physical View
[This section should describe how the various software components would be deployed in their physical
environment. Describe what software component will be installed on each machine in the system. Provide
a picture, as shown in the following example. Describe the picture in this section. ]
3CS/IVR Premise Gateway Physical Topology
Spectrum
ACD
3CS Linkage
Spectrum Cabinet
3CS
Infrastructure
3CS Server
Voice
Voice
ivrpgd:0
3CS
SDK
IVR 0
Thin Client
tuposd
IVR Server 0
ivrpgd:1
3CS
SDK
IVR Middleware Server
IVR 1
Thin Client
Legend:
Process Parent/Child Relationship
IVR Server 1
Voice
Data Link
Figure 2-2
7
Section 3 - System Level Sequence Diagram
[This section should provide an UML sequence diagram showing at a high level, the flow of messages
between the various software components in the solution.]
Overview
[Provide an overview of the sequence diagram here. Add an UML sequence diagram as shown in the
following example.]
IVRApp
ThinClient
Tuposd
ivrpgd
3CS SDK
1.()
2.()
MakeRequest
3.()
4.()
5.()
6.()
7.()
8.()
9.()
10.()
11.()
12.()
13.()
GetResponse
14.()
15.()
16.()
Figure 3-1
8
Description of Sequence Diagram
[Provide a detailed description of the above sequence diagram. Describe each step in the sequence diagram
in a bullet point. See below for an example]
The thin client communicates to both tuposd and the premise daemon via TCP/IP. Steps 1 through 8 are
for making a request and steps 12 through 16 are for getting the response. The following explains each
step:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
The IVR application makes a request to Tupos Client. The application passes along the service it
wishes to use (service id of the ivrpgd), the function code (of makeCall ), and the input parameters
(DN to call).
The ThinClient establishes a connection to the application server (tuposd) and passes along the service
information.
The application server returns the IP address and port of the requested service (ivrpgd) to the client.
Steps 2 and 3 are only executed the 1st time a new service is used.
The ThinClient establishes a connection to the service using the IP address and port it obtained from
tuposd.
The ThinClient sends the makeCall request packet to the premise daemon using the Tupos Object
transport mechanism.
The ivrpgd reads the new request packet from the socket. Since the request packet has a non-zero
function code, it gets queued for processing. The ivrpgd generates a new request ID and a new reply
packet for this request packet. The new reply packet is placed in its result table associated with the
request ID. Initially, the reply packet has a CCS_STILL_PROCESSING result code.
The ivrpgd returns a request ID back to the Thin Client.
The ThinClient returns the request ID to the IVR application.
The ivrpgd calls the 3CS server using the 3CS SDK to make the call.
The 3CS SDK returns an event corresponding to the makeCall request it received in step 9.
The ivrpgd updates the reply packet associated with the request ID (returned in steps 7 – 8) in its reply
table.
The IVR application calls the thin client again. This time, it passes the function code 0 (getReply), and
the request ID it received in step 8.
The Thin Client places the function code 0 and request ID in a request packet and sends the request
packet to the ivrpgd.
The ivrpgd looks in the reply table for the request ID. If the 3CS SDK has not responded by this time,
the reply packet would still say CCS_STILL_PROCESSING. Else, if the 3CS SDK has responded by
this time, the reply packet has the result for makeCall.
The ivrpgd sends the result packet to the Thin Client.
The thin client propagates the result packet to the IVRApp. The IVRApp now has the result for the
makeCall operation.
9
Section 4 – <Product name> Interface Definitions
[This section should describe in detail, the interfaces provided by the software component, being described
in this technical design. Describe the inputs and outputs for each function of the interface.]
Overview
[Provide an overview of the interface in this section. See example below]
The ivrpgd service will provide functionality that falls in four general categories:
1. Object Info Functions: Allows IVR to retrieve data about the current call from 3CS.
2. Telephony Functions: Enables IVR with third party call control via 3CS.
3. User Data Functions: IVR can send data to 3CS to attach to a call or retrieve attached data from
3CS for a given call.
4. Administrative Functions: Used for testing and administrative purposes.
5. getReply Function: Used to get the reply for a previous request.
The ivrpgd will utilize an asynchronous protocol for each function (unless explicitly stated otherwise).
This allows the IVR developer to keep control of the call flow and able to play voice treatment to the caller
if responses from 3CS Server are temporarily slowed due to heavy call volume.
Individual functions are identified by a function code. Function code 0 allows the IVR to retrieve results
from a previous request that was made via an asynchronous function call. All functions will return a value
to indicate the status of the request. If an error has occurred then a corresponding error message is
available.
All functions should set the client ID parameter to the IVR channel/lineID being used by the invoking IVR
application.
CTI Object Info Functions
Supported Call Information Types:
String
"ANI"
"CALLID"
"DNIS"
“APPLID”
“CALLEDNUM”
“CALLINGNUM”
“ARUVRUNAME”
“ARUVRUPORT”
“AGENTNAME”
Description
ANI number
CALL ID
DNIS number
APPLICATION ID
CALLED number
CALLING number
NAME of ARUVRU device
PORT of ARUVRU device
Agent name.
Function Code 1: getCallDefaultInfo
Description:
Gets the ANI, DNIS, and Call ID for the call.
Request Data:
10
<None>
Result Data:
position
[0]
[1]
[2]
value returned
(value of ANI)
(value of DNIS)
(value of CALL ID)
Administrative Functions
Function Code 98: echo
Description:
Echoes back the input of your packet and reports the port, IP, and Service ID being used
by the ivrpgd. This function is used only for debugging purposes.
Request Data:
<Anything>
Result Data:
Position
[0 .. n – 3]
[n –2]
[n – 1]
[n]
result data
echo data from client
port
IP
Service ID
Function Code 99: stop
Description:
Tells the running ivrpgd to exit.
Request Data:
<None>
Result Data:
<None>
11
Get Reply Function
Function Code 0: getReply
Description:
Will provide the Result Data (described by each of the function calls above) given a
request ID from a prior function call.
Request Data:
position
[0]
value
requestID from ivrpgd
Result Data:
<Dependent on function call. See Result Data sections above for detail>
12
Section 5 – <Product Name> Functionality Mapping to <Third
party SDK>
[The product being described in this document might use a third party SDK to provide the functionality it is
supposed to offer. This section should describe how the functions provided by the product map to the
methods, attributes and events of the third party SDK.]
Overview
[Add an overview of this section here. See example below]
This section describes how the IVR scripting interface methods map to the attributes, methods, and events
of the objects in the 3CS SDK.
Initialization
[Describe how the third party SDK is initialized. See example below].
During initialization, the ivrpgd loads all the ARUVRUDevices it is configured to monitor. The following
is the sequence of operations that will occur during initialization.
 The ivrpgd creates the ContactCenterSystem object. Calls Initialize and Login.
 Gets the ContactSourceCollection collection in ContactCenterSystem.
 Gets the first element in the collection, which should be the switch (RockwellContactSource) object.
 Gets the Entities collection in RockwellContactSource by the type eOTARUVRUDevice. This should
return a collection of entities, each of which is an ARUVRUDevice.
 From the list of ARUVRUDevices, it selects only those that it is configured to monitor, based on their
port numbers. Calls Load on each ARUVRUDevice.
 Creates and registers a sink for each ARUVRUDevice.
[Describe how each of the functions mentioned in the previous section map to the third party SDK. See
examples below].
getCallDefaultInfo



Obtains ANI from the Ani.Number attribute in the VoiceCall object.
Obtains DNIS from the Dnis.Number attribute in the VoiceCall object.
Obtains CALL ID from the Id attribute in the VoiceCall object.
getCallInfo








Obtains ANI from the Ani.Number in the VoiceCall object.
Obtains DNIS from the Dnis.Number in the VoiceCall object.
Obtains CALL ID from the Id attribute in the VoiceCall object.
Obtains APPLID from Application.Id in the VoiceCall object.
Obtains CALLEDNUM from CalledNumber attribute in the VoiceCall object.
Obtains CALLINGNUM from the CallingNumber attribute in the VoiceCall object.
Obtains ARUVRUNAME from the Name attribute in ARUVRUDevice object.
Obtains ARUVRUPORT from the PortNumber attribute in ARUVRUDevice object.
13
Section 6 – <Product name> Process Flow Diagrams
Overview
[This section should describe the various threads of execution in the product. Provide an overview of this
section here.]
Threads of execution in the ivrpgd
[Add a picture showing the various threads of execution in the executable as shown below].
This diagram shows the 3 different threads of execution that are part of the ivrpgd.
Request
processor
thread.
Main thread.
Request Queue.
Request 8
Request 7
Request 6
Request 5
Reply(result) table
3CS events
thread
request id 1
Result packet
request id 2
Result packet
request id 3
Still processing
request id 4
Still processing
Threads of execution in the ivrpgd
Figure 6- 1
Description:
[Provide a description of the above picture here. See example below.]
The 3 different threads of execution in the ivrpgd are:
1. The main thread. It initializes the ivrpgd and continuously listens for client requests. It puts the client
requests in the request queue. In case of getReply() requests, it looks up the result table and sends the
result back to the client.
2. The request processor thread. It dequeues the request and processes them. It updates the result table if
the result is already available at the end of processing the request.
3. The 3CS events thread. If 3CS events are needed to signal completion of a request, it is the 3CS events
thread of execution which updates the result table.
14
Main Thread Flow of Execution diagram
[Provide a flow chart showing the execution of this thread of execution as shown in the example below]
This diagram shows in detail, the flow of execution of the main thread in the ivrpgd.
Initialization Start
Navigate 3CS
objects and store
pointers of all
configured
ARUVRUDevices
Create 3CS CCS
object. Initialize
and Login.
begin loop
listening for client
requests.
create server
socket for ivrpgd
clients
no
Is function
code = 0?
Create and
register sinks for
ARUVRUDevice
objects.
Queue request for
processing and
return request id
to client.
Yes
return response
packet to client
Lookup response
packet for request
id from the result
table.
Figure 6- 2
Description:
[Provide a description of the flow chart here. See example below]
The main thread of execution initializes the ivrpgd. It opens up the server socket and continuously listens
for client requests. It puts the client requests in the request queue. In case of getReply() requests, it looks up
the result table and sends the result back to the client.
15
Request Processor Thread Flow of Execution diagram
[Add a flow chart for this thread of execution. See example below]
This diagram shows in detail, the flow of execution of the request processor thread in the ivrpgd.
Dequeue request
for processing
Determine function
code
Func code 1
Call
getCallDefaultInfo
Func code 2.
Call
getCallInfo
Func code 31.
Call
getKeyValue
Func code 10.
Call makeCall
Func code 11.
Call
singleStepTransfer
Func code 12
Call release
Func code 30
Call addList
Update result table
Flow chart for the request processor thread.
Figure 6- 3
Description:
[Add a description for the above picture here. See example below]
The request processor thread dequeues the request from the request queue. Based on the function code, it
calls one of the API functions. Functions like makeCall, singleStepTransfer, release and addList have to
wait for 3CS events to signal completion of the request. In case of functions like getCallDefaultInfo,
getKeyValue and getCallInfo, the result does not depend on 3CS events. In the latter case, the thread of
execution can update the result table immediately.
16
Section 7 – <Product name> Class Descriptions and Diagram
[This section should describe the various classes that are part of this product. The class diagrams should be
done using UML]
Overview
[Provide an overview of this section as shown in the example below]
This section describes the classes that are part of the ivrpgd and provides Class Diagrams using UML.
Please refer Figure 7-1 and Figure 7-2 for the class diagram.
Class Descriptions
[Provide a list of classes. Describe what each class does and the methods and attributes of each class. See
example below.]
TuposDmIPGD
This class is the starting point of the ivrpgd. It reads configuration information from the registry and
initializes the 3CS SDK. It creates the 3CS Contact system object and does the initialization and login. It
navigates the hierarchy of 3CS objects and creates a mapping of all the ARUVRUDevices it is configured
to service. It creates a sink for each ARUVRUDevice and associates the sink with the ARUVRUDevice
objects. It also initializes the server socket to accept connections from thin clients.
After initialization is complete, it begins the loop, which continuously processes client messages.
When a client request packet arrives on its request() method, it checks the function code. If the function
code is non zero, it queues the request in the TuposDmIPGQMgr. The TuposDmIPGQMgr returns a
request id, which is returned back to the client. If the function code is zero, it calls getReply() on the
TuposDmIPGQMgr to retrieve the result of a previous request. Below is a list of class members used in
this design.
Method: int go(int argc, char** argv);
Description: This method is the starting point of the application. argc and argv are the command line
arguments passed to the application.
Method: int init(int argc, char** argv);
Description: This private method does all the initialization necessary for the application. argc and argv are
the command line arguments passed to the application.
Method: static TuposDmIPGD* getInstance();
Description: Returns a pointer to the only instance of this singleton class.
Method: void begin();
Description: Implements the loop, which continuously processes client requests.
Method: int request (TuposTkSrzPacket* pPacket);
Description: This method provides the actual implementation for the request method of the
TuposTkRequestInterface. pPacket is a pointer to the request packet received from the client.
17
Class Diagram-Tupos Framework Related Classes
[Add an UML class diagram showing the classes that are part of the product. If there are too many classes
to be described, consider breaking up the class diagram into two or more smaller diagrams, so that it
doesn’t look too congested on paper. See examples below].
The following is a class diagram, which shows the various Tupos framework related classes that are part of
the ivrpgd and their relationships.
TuposDmSoPacketListener
+init()
+setRequestHandler()
«interface»
TuposTkRequestInterface
+request() : int
TuposTkRequestQ
1
1
+request()
+getReply()
+init()
+update()
1
TuposDmFuncRequestAdapter
1
1
+request()
«singleton»
TuposDmIPGD
+go()
-init()
+getInstance()
+request()
+begin()
«singleton»
TuposDmIPGQMgr
+getInstance()
+destroy()
TuposDmIPGAdminFuncs
«singleton»
TuposDmFuncTable
+execute()
+echo()
+stop()
1
1
1
TuposDmIPGInitConfig
TuposDmIPGAPIFuncs
+init()
+getCallDefaultInfo()
+getCallInfo()
+makeCall()
+singleStepTransfer()
+release()
+addList()
+getKeyValue()
TuposTkSoListenerCollection
+selectSo()
TuposTkFuncAbstract
+execute()
TemplateParameter
Legend
Class
Aggregation
Generalization
Qualified aggregation
Association
qualifier
Figure 7-1
18
Realizes
Dependency
-attributes
+operations()
Class Diagram - 3CS SDK Related Classes
The following is a class diagram, which shows the 3CS SDK related classes that are part of the ivrpgd and
their relationships.
&DIID_IContactCenterSystem
IDispEventImpl
TuposDmIPGAPIFuncs
«singleton»
TuposDmIPGD
+go()
-init()
+getInstance()
+request()
+begin()
1
1
1
1
1
TuposDmIPGContactCenterSystemSink
+sink
+ServerShutDown()
+RMIComplete()
1
+getCallDefaultInfo()
+getCallInfo()
+makeCall()
+singleStepTransfer()
+release()
+addList()
+getKeyValue()
1
1
+source
ContactCenterSystem
1
+CreateObject()
1
VoiceCall
0..1
1
+id
+Ani
+Dnis
+CustomProperties
+CallingNumber
+CalledNumber
+Clear()
ARUVRUDevice
+VoiceCalls
+Name
+PortNumber
+Call()
+SingleStepTransfer()
+source
1
+sink
1
«singleton»
TuposDmIPGARUVRUDeviceTable
+getARUVRUDevicePtr()
+getARUVRUDeviceSinkPtr()
+init()
1
1
1
TuposDmIPGARUVRUDeviceSinkPair
1
TuposDmIPGARUVRUDeviceSink
IVRPortNumber
+ARUVRUDevicePtr
+ARUVRUDeviceSinkPtr
1
+RMIComplete()
+RTEvent()
1
&DIID_IARUVRUDevice
IDispEventImpl
TemplateParameter
Legend
Class
Aggregation
Generalization
Qualified aggregation
Association
qualifier
Figure 7-2
19
Realizes
Dependency
-attributes
+operations()
Section 8 – <Product name> Collaboration Diagrams
[This section should describe the interaction between the various objects that are part of the product. The
interactions should be described using UML collaboration diagrams. Each collaboration diagram should
describe the execution of a particular functionality provided by the product. See examples below]
Overview
[Add an overview of this section here].
Queuing Client Requests
Data arrives in the socket from thin client
TuposTkSoListenerCollection
1 SocketReadyEvent
1.1 request
TuposDmSoPacketListener
TuposDmIPGD
[fn code = 1...99]
1.1.1 request
TuposDmIPGQMgr
Data is now queued in the Queue manager
and a request id is returned to the thin
client.
Figure 8. 1
Description:
[Describe each step in the above collaboration diagram in a tabular form as shown in the example below]
This diagram shows how client requests are queued in the Queue manager of ivrpgd.
Step
1
1.1
1.1.1
Description
Data arrives in the socket from the thin client. The TuposDmSoListenerCollection sends a
SocketReadyMessage to the TuposDmSoPacketListener.
The packet listener extracts the request from the socket and handles the request to
TuposDmIPGD.
If the function code is non zero, the TuposDmIPGD calls request on TuposDmIPGQMgr.
The request gets queued in TuposDmIPGQMgr and a request id is returned to the client.
20
Handling Client Reply Requests
Thin client calls getReply
TuposTkSoListenerCollection
1 SocketReadyEvent
1.1 request
TuposDmSoPacketListener
TuposDmIPGD
[fn code = 0]
1.1.1 getReply(request id)
TuposDmIPGQMgr
Queue manager looks up the result packet
for the request id. The result packet is sent
back to the thin client.
Figure 8-8
Description:
1
1.1
1.1.1
The thin client sends a getReply message and passes along the request id. The data arrives in
the socket and is read by the Tupos framework TuposTkSoListenerCollection object. The
TuposTkSoListenerCollection calls the SocketReadyEvent on TuposDmSoPacketListener
object.
The TuposDmSoPacketListener calls request on the TuposDmIPGD object.
TuposDmIPGD extracts the request id and function code (zero for getReply) . The
TuposDmIPGD calls getReply on the TuposDmIPGQMgr with the request id. The
TuposDmIPGQMgr looks up the result for the request id. The result packet is sent back to the
thin client.
21
Section 9 – <Product name> Configuration Options
[This section should describe the configuration options of the product. ]
Overview
[Add an overview of this section here].
Configuration Options
[Describe how the configuration options would be stored. Add a table which shows the configuration
options, their meaning and the default value. See example below].
ivrpgd will be configured primarily through the Windows registry. The following table shows the rsgistry
entries that will be recognized as well as the ivrpgd internal keys that correspond to the registry keys.
The configuration of the ivrpgd for NT is done with the Registry located at
HKEY_LOCAL_MACHINE\SOFTWARE\Tupos Framework\Tupos Application Server\ivrpgd:sid
Where sid should be the service instance id for that ivrpgd service. Normally the sid is 0.
All keys are stored and accessed as strings.
Internal Key
ll
ls
Registry Key
log_level
log_size
lf
lc
log_file
log_count
3CS_Application_Name
3CS_Application_Name
3CS_User_Name
3CS_User_Name
3CS_Password
3CS_Password
3CS_Switch_Index
3CS_Switch_Index
3CS_IVR_Name
3CS_IVR_Name
3CS_IVR_Ports
3CS_IVR_Ports
3CS_SDK_Ports
3CS_SDK_Ports
to_0
timeout_0
mrtk
max_replies_to_keep
22
Description
Level of detail in log file.
number of bytes to write to a
log file before rolling over to a
new log file.
path of the log file to write to.
number of old log files to keep
archived.
Application name used to
initialize
ContactCenterSystem object.
User name used by ivrpgd to
login to 3CS.
Password used by ivrpgd to
login to 3CS.
Index of the switch in 3CS
ContactSourceCollection.
Name of the IVR which
connects to ivrpgd.
Range of IVR ports to
monitor. These are assigned
by the IVR.
Range of IVR ports to
monitor. These are assigned
by the switch. The ivrpgd will
map each 3CS_IVR_Port with
the 3CS_SDK_Port.
Timeout in seconds of a socket
read.
Max number of replies to keep
stored in memory.
Default value
400
5000000
c:\logs\ivrpgd.log
2
ivrpgd:sid
None.
None.
None.
None.
None.
None.
5
200
Section 10 - Sign-off Sheet
Purpose
Signing and returning this section demonstrates that both parties have agreed to the design as proposed in
this document.
Directions
Please mail or fax this document to <Employee Name> at <Company Name> with:
 Each page initialized
 This section completed and signed
Contact Information
<Employee Name>
<Company Name>
<Company Address>
<City, State, Zip>
Office: <phone #>
Fax: <fax #>
Sign-off
Company Name
Employee Name
Employee Title
Employee Signature
Date
23
Download