title: ‘Print Delivery Paperwork for Purple Envelope Jobs’ slug: ‘print-delivery-paperwork-purple-envelope’ created: ‘2026-04-01’ status: ‘Implementation Complete’ stepsCompleted: [1, 2, 3, 4] tech_stack: [‘Classic ASP’, ‘VBScript’, ‘Access MDB (Jet/ACE)', ‘ReportMan ActiveX’, ‘ADO’, ‘FSO’, ‘ASPUnit’] files_to_modify:
Created: 2026-04-01
After inkjet export completes and the ImportService sets a Purple Envelope kit to Status = "Done", staff still need delivery paperwork to ship the job: shipping labels showing box counts and a packing slip for signed receipt. The Purple Envelope switchboard currently has no way to generate those documents.
Add a Print Delivery Paperwork action to the Purple Envelope workflow. When a kit is in Done status, the edit screen will show a button that calls a new KitController.PrintDeliveryPaperwork GET action. That action will:
SwitchBoardPurpleEnvelopeEditFindById.Done.DeliveryLabelPage staging table.Data\Delivery_Labels.rep.Data\Delivery_PackingSlip.rep.SwitchBoardPurpleEnvelopeEdit with flash messaging.In Scope:
DeliveryLabelPageDeliveryLabelPage_Class view modelKitRepository.SaveDeliveryLabelPages and KitRepository.DeleteDeliveryLabelPagesKitController.PrintDeliveryPaperwork GET actionPrint Delivery Paperwork button on SwitchBoardPurpleEnvelopeEdit.aspOut of Scope:
DoneImportService/TrackingDataImport.vbs sets kit status to Done after inkjet export. The web app should treat that as the gate for paperwork generation, not redefine the lifecycle.KitController.SwitchBoardPurpleEnvelopeEdit already loads the exact header data this feature needs, including JCode, Jurisdiction, JobNumber, Status, and LabelCount.App/Views/Kit/SwitchBoardPurpleEnvelopeEdit.asp already conditionally shows UI based on Model.Kit.Status; the new button should follow that same pattern.ExportTrackingLabels in KitController.asp is the nearest existing ReportMan export example, including connection-string setup, overwrite behavior, and FSO.MoveFile.MVC/activeXdepedancies.asp exposes a shared ReportManager, but HomeController.asp shows that creating a fresh Server.CreateObject("ReportMan.ReportManX") instance is acceptable when isolated state is preferable.MVC/lib.Data.asp confirms DAL.BeginTransaction, DAL.CommitTransaction, and DAL.RollbackTransaction are available.Tests/TestCase_PurpleEnvelopeReport.asp already use disposable MDB copies and are the right place to add repository-level coverage for this feature.| File | Purpose |
|---|---|
App/Controllers/Kit/KitController.asp |
Add PrintDeliveryPaperwork; reference ExportTrackingLabels for ReportMan + FSO export flow |
App/DomainModels/KitRepository.asp |
SwitchBoardPurpleEnvelopeEditFindById already exposes LabelCount, JCode, and Jurisdiction |
App/ViewModels/KitViewModels.asp |
Add DeliveryLabelPage_Class |
App/Views/Kit/SwitchBoardPurpleEnvelopeEdit.asp |
Add the Done-gated button |
Data/Migrations/Migration_20_Add_ColorId_To_InkjetRecords.asp |
Migration naming/style reference; next migration is Migration_21_... |
MVC/lib.Data.asp |
Confirms transaction and parameter-array behavior |
MVC/activeXdepedancies.asp |
Confirms ReportManX is already installed/used in the app |
Tests/TestCase_PurpleEnvelopeReport.asp |
Existing purple-envelope test fixture patterns to extend |
Use the existing Purple Envelope edit query.
SwitchBoardPurpleEnvelopeEditFindById already returns the required header fields and the inkjet-record-derived LabelCount. No new count query is needed.
Add a dedicated staging table.
ReportMan should read normal rows from Access rather than trying to derive reverse-ordered page slots inside the .rep file.
CREATE TABLE [DeliveryLabelPage] (
[ID] COUNTER CONSTRAINT [PrimaryKey] PRIMARY KEY,
[KitID] LONG NOT NULL,
[PageNum] INTEGER NOT NULL,
[Label1] TEXT(500),
[Label2] TEXT(500),
[Label3] TEXT(500),
[Label4] TEXT(500),
[Label5] TEXT(500),
[Label6] TEXT(500)
);
Repository owns staging-table lifecycle.
KitRepository.SaveDeliveryLabelPages will delete existing rows for the kit and insert the new set inside one transaction. KitRepository.DeleteDeliveryLabelPages will remove rows after both PDFs succeed. The controller should not issue raw DAL.Execute cleanup for this feature.
Page-building happens in VBScript, in reverse order.
For totalBoxes, start at boxNum = totalBoxes and fill Label1 through Label6 before creating the next page row. That yields page 1 containing the highest box numbers first.
Each PDF generation uses a fresh ReportManX instance.
Use Server.CreateObject("ReportMan.ReportManX") separately for labels and packing slip. This avoids any parameter/template state bleed between the two exports.
Direct URL access is guarded server-side.
The button is hidden unless status is Done, but the controller must also reject non-Done requests with a warning flash and redirect. UI-only gating is not sufficient.
Staging cleanup happens only after both PDFs are safely moved.
If generation fails after staging rows are written, leave them in place. A subsequent run will replace them because SaveDeliveryLabelPages always deletes and re-inserts by KitID.
Match existing export-folder naming.
Use the same ExportDirectory & JCode & "-" & Jurisdiction & "\" pattern already used by ExportTrackingLabels. Do not introduce new filename sanitization behavior in this feature.
Label text format is fixed. Each populated label slot is multiline text:
{Jurisdiction}
Box {X} of {TotalBoxes}
Total Printed {InkjetCount}
Job# {JobNumber}
Empty slots on the last page are "".
Output filenames are deterministic.
{JCode}-{Jurisdiction}_delivery_labels.pdf{JCode}-{Jurisdiction}_delivery_packing_slip.pdfDeliveryLabelPage migrationFile: Data/Migrations/Migration_21_Create_DeliveryLabelPage_Table.asp
<%
Class Migration_21_Create_DeliveryLabelPage_Table
Public Migration
Public Sub Up
Migration.Do "CREATE TABLE [DeliveryLabelPage] (" & _
"[ID] COUNTER CONSTRAINT [PrimaryKey] PRIMARY KEY, " & _
"[KitID] LONG NOT NULL, " & _
"[PageNum] INTEGER NOT NULL, " & _
"[Label1] TEXT(500), " & _
"[Label2] TEXT(500), " & _
"[Label3] TEXT(500), " & _
"[Label4] TEXT(500), " & _
"[Label5] TEXT(500), " & _
"[Label6] TEXT(500));"
End Sub
Public Sub Down
Migration.Do "DROP TABLE [DeliveryLabelPage];"
End Sub
End Class
Migrations.Add "Migration_21_Create_DeliveryLabelPage_Table"
%>
Files:
App/ViewModels/KitViewModels.aspApp/DomainModels/KitRepository.aspAdd:
Class DeliveryLabelPage_Class
Public PageNum
Public Label1
Public Label2
Public Label3
Public Label4
Public Label5
Public Label6
End Class
Add repository methods near the end of KitRepository_Class:
Public Sub SaveDeliveryLabelPages(ByVal kitId, ByVal pages)
dim sql, pageIt, page
sql = "INSERT INTO [DeliveryLabelPage] ([KitID],[PageNum],[Label1],[Label2],[Label3],[Label4],[Label5],[Label6]) VALUES (?,?,?,?,?,?,?,?)"
DAL.BeginTransaction
On Error Resume Next
DAL.Execute "DELETE FROM [DeliveryLabelPage] WHERE [KitID] = ?", CLng(kitId)
set pageIt = pages.Iterator
Do While Err.Number = 0 And pageIt.HasNext
set page = pageIt.GetNext()
DAL.Execute sql, Array(CLng(kitId), page.PageNum, page.Label1, page.Label2, page.Label3, page.Label4, page.Label5, page.Label6)
Loop
If Err.Number <> 0 Then
dim errNumber : errNumber = Err.Number
dim errDescription : errDescription = Err.Description
DAL.RollbackTransaction
On Error GoTo 0
Err.Raise errNumber, "KitRepository_Class.SaveDeliveryLabelPages", errDescription
End If
On Error GoTo 0
DAL.CommitTransaction
End Sub
Public Sub DeleteDeliveryLabelPages(ByVal kitId)
DAL.Execute "DELETE FROM [DeliveryLabelPage] WHERE [KitID] = ?", CLng(kitId)
End Sub
PrintDeliveryPaperwork to KitControllerFile: App/Controllers/Kit/KitController.asp
Add a new parameterless GET action after SwitchBoardPurpleEnvelopeEdit and before Index.
Implementation requirements:
Id from Request.QueryString("Id")KitRepository.SwitchBoardPurpleEnvelopeEditFindByIdDone, set Flash.Warning and redirect back to SwitchBoardPurpleEnvelopeEditLabelCount <= 0, set Flash.Warning and redirect.rep files exist before writing staging rowsLinkedList_Class of DeliveryLabelPage_Class rows in reverse orderKitRepository.SaveDeliveryLabelPagesReportMan.ReportManX object using PBKITIDReportMan.ReportManX object using parameters:
PJURISDICTIONPJOB_NUMBERPTOTAL_PRINTEDPTOTAL_BOXESKitRepository.DeleteDeliveryLabelPages only after both PDFs succeedFlash.Success and redirect back to SwitchBoardPurpleEnvelopeEditConcrete page-build algorithm:
If inkjetCount > 0 Then
totalBoxes = Int((inkjetCount + 1099) / 1100)
Else
totalBoxes = 0
End If
set pages = new LinkedList_Class
boxNum = totalBoxes
pageNum = 1
Do While boxNum >= 1
set page = new DeliveryLabelPage_Class
page.PageNum = pageNum
For slot = 1 To 6
labelText = ""
If boxNum >= 1 Then
labelText = jurisdiction & vbCrLf & _
"Box " & boxNum & " of " & totalBoxes & vbCrLf & _
"Total Printed " & inkjetCount & vbCrLf & _
"Job# " & jobNumber
boxNum = boxNum - 1
End If
Select Case slot
Case 1 : page.Label1 = labelText
Case 2 : page.Label2 = labelText
Case 3 : page.Label3 = labelText
Case 4 : page.Label4 = labelText
Case 5 : page.Label5 = labelText
Case 6 : page.Label6 = labelText
End Select
Next
pages.Push page
pageNum = pageNum + 1
Loop
Connection-string and export behavior should mirror ExportTrackingLabels, but use local report objects:
dim labelsReport : set labelsReport = Server.CreateObject("ReportMan.ReportManX")
dim slipReport : set slipReport = Server.CreateObject("ReportMan.ReportManX")
Done-gated button to the Purple Envelope edit viewFile: App/Views/Kit/SwitchBoardPurpleEnvelopeEdit.asp
Insert this above the existing Ready To Assign STIDS block so it is visible when the job is already complete:
<% If Model.Kit.Status = "Done" Then %>
<p>
<%= HTML.LinkToExt("<i class='glyphicon glyphicon-print'></i> Print Delivery Paperwork", "Kit", "PrintDeliveryPaperwork", Array("Id", Model.Kit.ID), Array("class", "btn btn-primary")) %>
</p>
<% End If %>
File: Tests/TestCase_PurpleEnvelopeReport.asp
Add:
A DB-backed test that seeds a Purple Envelope kit, calls SaveDeliveryLabelPages, and verifies inserted row count and label values
A DB-backed test that calls SaveDeliveryLabelPages twice for the same kit and proves the second run fully replaces the first
A DB-backed test for DeleteDeliveryLabelPages
A source-level guard test asserting the view contains the Model.Kit.Status = "Done" condition and PrintDeliveryPaperwork link
A source-level guard test asserting KitController.asp defines Public Sub PrintDeliveryPaperwork
Task 6: Create the two ReportMan templates
Files:
Data/Delivery_Labels.repData/Delivery_PackingSlip.repDelivery_Labels.rep
TRACKINGKITLABELSPBKITIDSELECT Label1, Label2, Label3, Label4, Label5, Label6 FROM DeliveryLabelPage WHERE KitID = [PBKITID] ORDER BY PageNumDelivery_PackingSlip.rep
PJURISDICTIONPJOB_NUMBERPTOTAL_PRINTEDPTOTAL_BOXESStatus = "Done", when SwitchBoardPurpleEnvelopeEdit renders, then the Print Delivery Paperwork button is visible.Done, when the page renders, then the button is not visible.PrintDeliveryPaperwork for a kit whose status is not Done, when the action runs, then it redirects back with a warning flash and produces no PDFs.totalBoxes = 1 and the staged row has Label1 = "Box 1 of 1" with Label2 through Label6 blank.totalBoxes = 2 and the staged row contains Label1 = "Box 2 of 2" and Label2 = "Box 1 of 2".Box X of Y, Total Printed N, and Job# N on separate lines.JCode = "01234" and Jurisdiction = "Anytown", when paperwork generation succeeds, then 01234-Anytown_delivery_labels.pdf exists in ExportDirectory\01234-Anytown\.01234-Anytown_delivery_packing_slip.pdf exists in the same export folder.SwitchBoardPurpleEnvelopeEdit with a success flash.DeliveryLabelPage rows already exist for the kit, when paperwork is generated, then those rows are replaced by the new set and removed after both PDFs succeed..rep file is missing, when the action runs, then the user receives a warning flash and the request does not crash with a 500.ReportMan.ReportManX ActiveX installed on the IIS hostFSO and DAL globals already loaded through App/include_all.aspExportDirectory and dev from App/app.config.aspLinkedList_Class from the shared MVC librariesDelivery_Labels.rep and Delivery_PackingSlip.rep present in Data\DeliveryLabelPage migration applied to the active MDB before useTests/Test_All.asp after adding the repository and source-guard tests.Tests/TestCase_PurpleEnvelopeReport.asp.Done button visibilityDone kitsQuick Dev using /bmad-bmm-quick-dev in a fresh context.Powered by TurnKey Linux.