Correspondence
Module: correspondence. The register of letters, emails, transmittals and other documents exchanged with the client and vendors: incoming and outgoing, filed in its own folder tree, with attachments.
How this page was verified
Written from master on 2026-09-06 and compared with the big five the same day. The screen section was rewritten on 2026-09-07 with the screens opened on inact-jadestone.eris.place (the grid, project AAL) and inact-ktp.eris.place (the Add dialog); the KTP snapshot has no correspondence rows.
What it is
Correspondence mirrors the Document Library with its own tables:
| Layer | Table | Holds |
|---|---|---|
| Folders | ts_corr_library | library_id, library_code, library_desc, library_parent, contract_ref, library_type, project_id. A tree per project. |
| Correspondence | ts_correspondence | corr_no, corrkind_id (1 = Incoming, 2 = Outgoing), corrtype_id, corrcat_id, corr_doc_number, corr_title, corr_procsheetno, corr_send_received, library_code, corr_transno, corr_notes, company_id, corr_preparedby, corr_from_to, corr_doc_original, project_id, doc_res_id, issued_code, audit columns |
| Files | ts_file_explorer, linked by ts_map_corr_file | the physical files |
| Links between letters | ts_map_corr_corr | corr_no to corr_doc_number, a reply or reference chain |
Three reference tables classify a row: kind (ts_corrkind: Incoming, Outgoing), type (ts_corrtype: Email, Fax, Letter, Technical Note, Document, Progress Report, Reference File) and category (ts_corrcat, per project).
Who writes correspondence
Users write it by hand through this module. Two other features write it for them:
- Upload Transmittal inserts an Incoming row (
corrkind_id=1) for the received Transmittal Sheet and files it under the project's incoming-transmittal default folder. - Return inserts an Outgoing row (
corrkind_id=2) for the Transmittal Out package, throughhandleProcessTransmittalCorrespondence()inrouting.inc.php.
The two default folders are per-project rows in ts_incoming_transmittal_default_folder and ts_outgoing_transmittal_default_folder (project_id, library_id), added June 2026.
The screen

correspondence.php with correspondence_browse.htm, the same three-part layout as the Document Library: a folder tree (cmd=groupby, from ts_corr_library), a grid of the rows in the selected folder, and per-row detail (cmd=docdetail). No tabs. The grid columns, from get_doc_column() in correspondence.inc.php: ID, In/Out, Sent/Received, Correspondence (the number), Proc Sheet No., Title, Attachments, Notes, Type, Category, From/To, Prepared by, Folder, Project. The + on a row opens the references sub-grid (cmd=subgrid), the letters linked through ts_map_corr_corr.
Toolbar
New, Edit, Delete, Copy and Upload are added together when the user's group has edit or add on correspondence (havePrivileges($_LOGIN_GROUP_ID, ...) in correspondence.php, the old group check, not the resource-group one); the rest are fixed in the template.
| Button | Action |
|---|---|
| New | the Add Correspondence dialog, act=add, on $pdo |
| Edit | act=edit, on $pdo |
| Delete | act=deletedata, on $pdo |
| Copy | the Add dialog pre-filled from the selected row |
| Upload | attachments through the multi-file uploader (correspondence_multiupload_upload.php, on $pdo: writes ts_file_explorer and ts_map_corr_file) |
| Refresh, Search, Sort | reload; field / operator / value search (cmd=search); sort |
| Export CSV | cmd=exportCSV |
the customisable listing, cmd=print_costume, dead where the legacy helper throws (see below) | |
| Download | batch download of the selected rows' files (cmd=batchdownload) |

The Add dialog writes one ts_correspondence row: corrkind_id from In/Out, corr_send_received, corr_doc_number, corr_title, corr_from_to, corrtype_id, corrcat_id, issued_code, corr_transno, library_code (the folder picked in the tree), corr_preparedby, corr_notes, and the In reference to rows into ts_map_corr_corr. Files go through the same uploader as the Upload button.
Per-row: View attachments (cmd=viewattach), Routing detail (cmd=routdetail), Detail (cmd=docdetail).
Folder access
ts_corr_library_priv limits folders per user group (library_id × group_code). Note the difference from the Document Library: this table still keys on the old group_code, not on the resource group. correspondence_privilege.inc.php applies it.
Correspondence routing
The schema has a full second routing model for correspondence: ts_routing_corr, ts_map_routing_file_corr, ts_map_routing_to_corr, ts_routing_group_corr, ts_routing_group_user_corr and ts_routing_action_indicated_corr. The grid joins ts_routing_corr and ts_map_routing_to_corr to show routing state per row. The code that attaches correspondence files to a routing (addTo handler at the top of correspondence.php, writing ts_map_routing_file_corr) runs on iw_mysql_query(). No file in modules/routing writes the _corr tables.
Treat correspondence routing as legacy
In master, Jadestone, Medco and Timas the only writer of the _corr routing tables throws on entry. Whether any instance still routes correspondence needs a check against live data before anyone builds on it.
What still runs on the legacy helper
The module is a hybrid. Counted on 2026-09-06 over live lines: 50 calls to iw_mysql_query() and 116 uses of $pdo. Where the legacy helper throws (every fork except JOTRE), these paths are dead:
| Path | File | State |
|---|---|---|
Inline grid edit, act=editdata | correspondence_act.inc.php | dead |
Select document, act=selectDoc | correspondence_act.inc.php | dead |
Unpublish, act=unpublish | correspondence_act.inc.php | dead |
Attach an existing file (mapFile) and the addTo routing-file handler | top of correspondence.php | dead |
Print listing, cmd=print_costume | correspondence_print.inc.php, 12 legacy calls, no $pdo | dead |
| The old file explorer | file_explorer.php | dead |
The project list at correspondence.php line 293 | correspondence.php | dead where reached |
New, Edit, Delete, the tree, the grid, the multi-file upload and the subgrid are on $pdo and work everywhere.
Database tables affected
| Table | Operation | By |
|---|---|---|
ts_correspondence | insert / update / delete | New, Edit, Delete; Upload Transmittal; Return |
ts_file_explorer, ts_map_corr_file | insert | Upload |
ts_map_corr_corr | insert / delete | the reference field on the form |
ts_corr_library, ts_corr_library_priv | select | tree and access |
ts_routing_corr, ts_map_routing_to_corr, ts_map_routing_file_corr | select, and a dead insert | grid, legacy routing attach |
Gotchas
- Two folder trees, two access models. Document Library folders are
ts_doc_librarywith resource-group access; correspondence folders arets_corr_librarywith user-group access. They do not share codes. - A transmittal is a correspondence row. When a Transmittal Sheet "disappears", look in this module's incoming folder, not the Document Library.
- The print listing is dead in four forks. Users get a fatal error from the Print button. The Reporting menu's DMS reports do not point at this module, so nothing else covers it.
ts_correspondencehas no foreign keys.company_id,corrcat_idandlibrary_codecan point at nothing after a delete.
Instance differences
Checked on 2026-09-06.
| Instance | Difference |
|---|---|
| Timas | No Batch download in the template (batchdownload_submit and close_act_download absent). correspondence_addedit.inc.php and the upload handler differ from master. |
| JOTRE | All legacy paths above work, because iw_mysql_query() still runs. correspondence_addedit.inc.php and the upload handler differ from master. |
| Medco | Upload handler and subgrid differ from master; same buttons. |
| Jadestone | Tree and subgrid differ from master; same buttons. |
The 50 legacy calls are the same in every fork.
Related
- Upload Transmittal and Return: the automatic writers.
- Document Library: the sibling module for project documents.