Routing Overdue
Kode report: routing_01. Membuka modul routing dengan show=report&print=due; routing_handler_print.php meng-include routing_handler_print_dueroute.php, 614 baris, memakai $pdo. Satu baris per penerima sebuah routing (ts_map_routing_to), dengan dokumen routing-nya, aksi yang diminta dari orang itu, due date dan berapa hari tersisa. Walau namanya begitu, report ini tidak terbatas pada baris overdue: filter default-nya Route Status = open, dan kolom Days Remaining adalah tempat "overdue" tampil sebagai angka negatif.
Cara halaman ini diverifikasi
Ditelusuri di master pada 2026-09-06 dan dibandingkan dengan big five dan KTP. Screenshot dari inact-ktp.eris.place, project SNS, Template A dengan Record Grouping.
Form filter

view=custom merender routing_print_due_custom.htm:
| Kontrol | Field | Efek |
|---|---|---|
| Project | project | daftarnya dari getProjectPersonByResource(): semua project aktif untuk admin, project milik user untuk yang lain |
| Show All Data | condition[]=show_all | membuang semua kondisi di bawah; pilihan template tetap berlaku |
| Show Only Latest Revision | only_latest_rev | menyimpan, per nomor dokumen, routing dengan rout_id tertinggi yang file utamanya dokumen itu. Ini "routing terakhir", bukan "revisi terakhir" |
| Conditions | field[], operator[], what[] | baris default: Route Status equals open. Field berupa nama kolom mentah (r.rout_status, rout_doc_number, rt.rout_indicate, rout_due_date, ...); add search field menambah baris, semua digabung AND |
| Template A / B / C | condition[]=A dst. | set kolom, dari json/table_header.json |
| Record Grouping | order[] | kalau ada, nilai berulang dikosongkan sehingga baris terbaca sebagai grup |
| Preset | preset, name | set kondisi tersimpan; disimpan oleh act=save_preset di routing_handler_post.php, namanya dicetak di judul |
Kondisi tanggal (rout_due_date, rout_date, rt.rout_resp_date, rt.rout_initials) dikonversi dari format tanggal INACT; nilai tanggal kosong berubah menjadi ISNULL(field), sintaks MySQL yang gagal di PostgreSQL dan SQL Server. Field originator memaksa operator menjadi =.
Query-nya
Satu SELECT atas ts_map_routing_to rt, di-join ke ts_routing r, author (ts_org_person), perusahaan originator, resource dan person penerima, ts_routing_action_indicated, dan subquery atas ts_map_routing_file yang mengembalikan file pertama tiap routing (rout_type tidak diperiksa; map_id terendah menang, biasanya dokumen utama). Difilter r.rout_project_code = <project>, daftar revisi terakhir dan kondisi.
Kolom hitungan per baris adalah Days Remaining. Ia membandingkan dua tanggal saja:
- due date penerima,
ts_map_routing_to.rout_due_date, kolom Due Date di baris yang sama (tiap penerima punya due date sendiri; routing-nya sendiri tidak punya due date), dan - hari ini, jam server database saat report dijalankan. Bukan tanggal sign-off, bukan tanggal terima.
Days Remaining = rout_due_date − hari ini (dalam hari bulat)Jadi +3 berarti due date tiga hari lagi, 0 berarti jatuh tempo hari ini, dan -222 berarti due date sudah lewat 222 hari. Angkanya hanya dicetak selama Action Taken baris itu masih Open; begitu penerima sudah sign-off, selnya kosong, apa pun tanggalnya.
Di screenshot Template B report dijalankan pada 07/Sep/2026. Baris dengan Due Date 28/Jan/2026 menampilkan -222: 28 Januari sampai 7 September adalah 222 hari, dan barisnya masih Open, jadi reviewer terlambat 222 hari. Baris dengan Due Date 15/Aug/2024 tidak menampilkan apa-apa karena sudah sign-off.
Per driver:
| Driver | Ekspresi | Tanda |
|---|---|---|
| MySQL | DATEDIFF(rt.rout_due_date, now()) | due date dikurangi hari ini: positif = hari tersisa, negatif = hari terlambat |
| PostgreSQL | EXTRACT(DAY FROM (rt.rout_due_date - now())) | sama |
| SQL Server | DATEDIFF(DAY, rt.rout_due_date, GETDATE()) | hari ini dikurangi due date, jadi tandanya terbalik: positif = hari terlambat |
Urutan diturunkan dari template: setiap kolom setelah yang pertama, kecuali Routing Sequence, menjadi kunci ORDER BY sesuai urutan template. Di MySQL handler menjalankan SET sql_mode = '' lebih dulu, karena subquery file memakai GROUP BY longgar. Di SQL Server subquery ditulis ulang dengan ROW_NUMBER() dan rout_sequence_no diformat dengan desimal koma. SQL lengkapnya ditulis ke error log PHP di setiap eksekusi (error_log(print_r($sql, true))).
Kolomnya
Tiga template, dari table_header.json. Ini bukan tiga set kolom dari satu daftar: template juga menentukan urutan sort dan pengelompokan, karena setiap kolom setelah yang pertama menjadi kunci ORDER BY sesuai urutan template, dan Record Grouping mengosongkan kolom-kolom depan saat berulang. Jadi baris yang sama terbaca sebagai tiga report berbeda.
| Template A | Template B | Template C | |
|---|---|---|---|
| Pertanyaan yang dijawab | Bagaimana keadaan tiap routing? | Apa yang ada di meja tiap orang? | Bagaimana tiap routing bergerak lewat sequence-nya? |
| Diurutkan dan dikelompokkan per | routing (Route ID, judul, status, dokumen, rev, author), lalu penerima urut sequence | orang (Routing To), lalu action, due date | routing, lalu penerima urut sequence |
| Dikosongkan saat berulang | tujuh kolom routing, dicetak sekali per routing | empat kolom orang (Routing To, Action Indicated, Due Date, Days Remaining), dicetak sekali per orang dan action | tujuh kolom routing, seperti A |
| Kolom | No, Route ID, Route Title, Route Status, Doc.No., Rev, Author, Routing To, Action Indicated, Due Date, Action Taken, Response, Days Remaining | No, Routing To, Action Indicated, Due Date, Days Remaining, Action Taken, Response, Route ID, Route Title, Route Status, Doc No, Rev, Author | A plus Routing Sequence, Receive Date (rout_initials) dan Sign-Off Date (rout_resp_date) |
| Dipakai untuk | daftar overdue mingguan per dokumen | mengejar reviewer: satu blok per orang, baris overdue negatif di Days Remaining | audit: kapan tiap sequence mulai, kapan tiap orang sign-off |



| Kolom | Sumber |
|---|---|
| Routing To | resource_name (person_id), dibangun dengan CONCAT di query; resource_name (No user) kalau resource tidak punya person. Di Jadestone kurungnya berisi nama person, bukan id, lihat perbedaan antar instance |
| Action Indicated | ts_routing_action_indicated.action_desc |
| Action Taken | rout_status_resp dipetakan lewat $_ROUT_STATUS: N Open, 1 re-Route, 2 Route as New, 3 Return, 4 Sign Off, 5 Closed Without Action |
| Response | rout_response, teks bebas atau result code yang dimasukkan saat sign-off |
| Days Remaining | rout_due_date − hari ini untuk baris penerima itu, lihat di atas; hanya dicetak selama Action Taken masih Open (rout_status_resp = 'N'); baris yang sudah sign-off tidak menampilkan apa-apa |
| Routing Sequence | rout_sequence_no, langkah tempat penerima berada; semua penerima di nomor yang sama dikirim bersamaan |
| Receive Date | rout_initials, tanggal mulai yang direncanakan untuk langkah penerima, lihat di bawah. Walau labelnya begitu, ini bukan hari routing sampai di inbox |
| Due Date | rout_due_date, due date milik penerima sendiri, dihitung dari Receive Date |
| Sign-Off Date | rout_resp_date, hari penerima menjawab; kosong selama Open |
Hanya Jadestone: Issued Status setelah Rev

Ditambahkan oleh INA27-299 (Done) ke ketiga template, di keluaran HTML dan ekspor Excel. Nilainya ts_issued_status.issued_desc untuk issued_code file routing, di-join pada project report (LEFT JOIN ts_issued_status i ON i.issued_code = rf.issued_code AND i.project_id = <project>), jadi terbaca Issued for Review, bukan IFR, teks yang sama dengan yang ditampilkan Inbox. Routing yang file-nya tidak punya issued code mencetak kosong.

Dua perubahan ikutan: Record Grouping di Template A dan C sekarang mengosongkan delapan kolom berulang, bukan tujuh, karena kolom baru ini setingkat dokumen dan harus ikut terlipat dengan routing-nya; dan daftar field filter mendapat Issued Status (rf.issued_code). Master dan fork lain tidak punya kolom ini.
Receive Date dan Due Date, dan kapan berubah
Keduanya kolom date di ts_map_routing_to, satu pasang per penerima, dan keduanya ditulis sekali, saat baris penerima dibuat. Tidak ada yang menulis ulang setelahnya: mengirim sequence berikutnya hanya membalik rout_is_oninbox, dan sign-off hanya menulis rout_resp_date dan rout_status_resp. Tidak ada UPDATE ... SET rout_initials di mana pun di modul routing.
Cara pengisiannya bergantung pada asal barisnya:
| Baris dibuat oleh | Receive Date (rout_initials) | Due Date (rout_due_date) |
|---|---|---|
| Upload dari Distribution Matrix | sequence 1: hari upload, digeser keluar dari akhir pekan oleh get_santos_startdate(). Tiap sequence berikutnya: sehari setelah due date sequence sebelumnya | Receive Date plus Review Time project untuk issued status itu (ts_workingdays), melewati akhir pekan dan ts_holiday, oleh get_santos_duedate() di business_day_santos.inc.php. Baris dengan action yang sama menyalin pasangan dari baris pertama, jadi setiap reviewer di satu langkah berbagi tanggal |
Add di Routing Slip (routing_handler_ajax.php) | hari ini | tanggal routing plus hari review; kalau routing sudah lewat jatuh tempo, hari ini plus satu hari |
Submit Routing dari form (routing_handler_post.php) | apa pun yang diketik user di sel Start Date grid Routing To | apa pun yang diketik user di Due Date |
Jadi seluruh jadwal sebuah routing disusun di hari pertama, sequence demi sequence, dari review time. Kalau reviewer 1 sign-off terlambat, Receive Date dan Due Date reviewer 2 tidak digeser: reviewer 2 menerima routing di inbox-nya setelah Receive Date yang direncanakan, dan Days Remaining untuk reviewer 2 dihitung terhadap due date yang mungkin sudah dekat atau lewat. Itulah angka yang ditampilkan report ini, dan itu sebabnya reviewer pertama yang terlambat membuat setiap langkah berikutnya tampak overdue.
Routing Slip menampilkan dua kolom yang sama sebagai Start Date dan Due Date; report mengganti nama yang pertama menjadi Receive Date. Form filter mendaftarnya dengan nama lamanya, Sequence Start Date.

Record grouping
Dengan order[] ada, baris sudah diurutkan per kolom template, dan handler mengosongkan sel yang berulang sehingga tiap routing (Template A dan C, tujuh kolom pertama) atau tiap orang (Template B, empat kolom pertama) dicetak sekali. Barisnya tidak digabung; perubahan di kolom mana pun yang lebih awal memulai grup baru. Tanpa grouping setiap sel dicetak.
Masalah yang diketahui
- Days Remaining bertanda terbalik di SQL Server. Report Medco terbaca "terlambat" di mana instance MySQL terbaca "tersisa".
- Latest Revision sebenarnya routing terakhir:
rout_idtertinggi per dokumen, revisi apa pun yang dibawanya. - Subquery file mengabaikan
rout_type; routing yang file pertamanya lampiran mencetak nomor lampiran di Doc.No. - Cabang
doc_titledi loop baris mencetak tanggal sign-off, tetapi tidak ada template yang punya kunci itu, jadi tidak terjangkau. Jangan menambah kolom Doc Title ketable_header.jsontanpa memperbaikinya. - Setiap eksekusi mencatat SQL ke error log web server.
ISNULL(...)untuk kondisi tanggal kosong adalah sintaks MySQL; di PostgreSQL dan SQL Server query-nya gagal.
Perbedaan antar instance
Diperiksa 2026-09-06 dengan diff handler.
| Instance | Perbedaan |
|---|---|
| JOTRE (116 baris) | Subquery file dan set kolom yang ditulis ulang; database QA-nya memasang entri tunggal yang sama. |
| KTP (62 baris) | Blok filter lebih lama; kolom keluaran identik. |
| Jadestone | INA27-293 (sudah di-merge ke main 2026-09, Ready for deployment): Routing To terbaca Resource Name (Person Name), bukan Resource Name (person_id), di ketiga template, di keluaran HTML dan di ekspor Excel (excel/export_excel.php), karena person id di Jadestone berupa alamat email yang tidak dikenali orang. Dropdown filter Routing To terbaca Person Name (Resource Name) (routmakeFieldValue() di routing.inc.php); nilai yang dikirim tetap resource id, jadi preset tersimpan tetap jalan. Resource Name (No user) tidak berubah. INA27-299 (Done): kolom Issued Status setelah Rev di ketiga template, lihat di atas. Juga punya Routing Overdue Summary sendiri (INA27-296). |
| Prima Energy (23 baris) | Blok filter lebih lama: tanpa field filter Originator (Company / Person) dan Discipline, docdisc_id tidak dibawa di subquery file, dan query hanya menghitung penerima yang masih di inbox (rt.rout_is_oninbox = 1). Dua panggilan iw_mysql_query masih ada; helper-nya melempar exception, jadi jalur itu fatal kalau tercapai. Diperiksa lewat diff pada 2026-09-08, belum ditelusuri. |
| Timas (19 baris), Medco (3 baris) | Kosmetik. Medco menambah report Comment Summary terpisah (print=commentsummary). |


Terkait
- Action Indicated: arti kolom action.
- Sign Off: yang mengisi Action Taken dan Response.
- Setting General: hari libur di balik due date.