Home / Demo
CareWell clinic
Five Forms modules with a menu module and an attached PL/SQL library: sign-in with a list of values, a home page, patients, appointments (a list item, a double-booking check) and billing (invoices with lines and payments, an invoice that cannot be deleted).
Target: .NET 10 and PostgreSQL, the forms, the menu and the library's shared state in the browser. Original Forms source:
github.com/devvinish/oracle-forms-book-code
at commit 8c1281a, licence: MIT, copyright 2026 Vinish Kapoor.
Demo login: Sign in as ADMIN, RECEPTION1 or BILLING1 (the original has no passwords).
The live demos share one database per app: visitors see each other's changes, and the data resets to the scenario fixture every night.
Parity: 22 of 22 scenarios
Each scenario was recorded on the original and replayed against the migrated app. Three runs from a fresh database gave byte-identical diffs for every scenario; none has a defect. Open a scenario for its steps, screenshots of both apps, the golden record, the diff and its waivers.
- Match: the same value. Tolerated: different only within a written rule of the tolerance policy, here today's appointment counts on the home page, which depend on the day of the run, and a new payment's date, which defaults to today.
- Waived: 6 waivers are proposed for the customer's decision; 6 of them cover 209 values here, where the migrated app deliberately does not copy the original (see waivers).
- Defect: a difference to repair. Unmapped: none; every recorded value has a counterpart in the migrated app.
| Scenario | What it does | match | tolerated | waived | defect | unmapped | Three runs |
|---|---|---|---|---|---|---|---|
| appointments-book | Book an appointment for the first patient (Adam Ali). CTL.APPTS opens CW_APPOINTMENTS for the patient (CW_NAV.OPEN_MODULE sets CW_CTX.PATIENT_ID; LOAD_PATIENT queries). WHEN-NEW-FORM-INSTANCE fills the department list from RG_DEPTS. Records > Insert adds a row; the department list and the doctors' LOV (RG_DOCTORS, the department's active doctors) fill it. File > Save validates the record (CHECK_DOUBLE_BOOKING) and inserts it (PRE-INSERT: sequence, CHECK_DOUBLE_BOOKING again). | 847 | 28 | 11 | 0 | 0 | identical |
| appointments-cancel | Cancel an appointment. Choosing Cancelled fires WHEN-LIST-CHANGED: SET_REASON_REQUIRED makes REASON required for that record. With the reason emptied, File > Save stops at FRM-40202, which ON-ERROR (CW_ERR.ON_ERROR) passes on as the Forms message. With a reason the update goes through: PRE-UPDATE's CHECK_DOUBLE_BOOKING returns at once for a cancelled appointment. | 839 | 27 | 11 | 0 | 0 | identical |
| appointments-delete-refused | Delete a completed appointment that has a visit. Records > Delete removes it from the block; File > Save posts the delete, the database refuses it with ORA-02292 (VISITS_APPT_FK), and ON-ERROR (CW_ERR.ON_ERROR) shows its translation "Other records still refer to this one." Nothing is deleted. | 525 | 18 | 8 | 0 | 0 | identical |
| appointments-department | Change an appointment's department. WHEN-LIST-CHANGED on DEPT_ID looks up the doctor's department: a doctor of another department is cleared. Changing it again, with no doctor left, skips the lookup. File > Clear then asks whether to save the changes (the Forms dialog); No discards them. | 623 | 32 | 9 | 0 | 0 | identical |
| appointments-double-booking | Book Dr Kavya Pillai at 13:40 on 26 October 2026, when she already sees the patient from 13:30 to 14:00 (appointment 51140). WHEN-VALIDATE-RECORD runs CHECK_DOUBLE_BOOKING, which finds the overlap, shows the message and raises FORM_TRIGGER_FAILURE: nothing is saved. | 838 | 28 | 11 | 0 | 0 | identical |
| appointments-invalid-duration | An appointment of 300 minutes. The form accepts it; the database refuses it (check constraint APPOINTMENTS_DUR_CK), and ON-ERROR's CW_ERR.ON_ERROR turns the error into "An appointment lasts 5 to 240 minutes." through CW_ERR.CONSTRAINT_OF. | 839 | 28 | 11 | 0 | 0 | identical |
| appointments-no-patient | Clinic > Appointments from the home page, before any patient was chosen: LOAD_PATIENT finds no current patient (CW_CTX.PATIENT_ID) and says "Choose a patient in Patients first." | 76 | 17 | 4 | 0 | 0 | identical |
| appointments-return | Back to the open appointments of the same patient. Clinic > Patients goes to the open CW_PATIENTS; Appointments... with the same current patient finds CW_APPOINTMENTS open and goes to it with GO_FORM. Its WHEN-FORM-NAVIGATE runs LOAD_PATIENT, which sees the patient already loaded and does nothing. | 421 | 15 | 7 | 0 | 0 | identical |
| billing-delete-refused | Records > Delete on an invoice. The INVOICES block does not allow deletes, so Forms refuses with FRM-41049 before the master-detail check (ON-CHECK-DELETE-MASTER) could run. | 190 | 56 | 6 | 0 | 0 | identical |
| billing-patient | Invoices of one patient. Appointments... in CW_PATIENTS puts the first patient into the shared CW_CTX (CW_NAV.OPEN_MODULE). Clinic > Home goes back to CW_MAIN, whose menu was set up for the administrator, and its Clinic > Invoices opens CW_BILLING: LOAD_INVOICES finds the patient in CW_CTX and shows only that patient's invoices. | 465 | 27 | 7 | 0 | 0 | identical |
| billing-pay | Pay two invoices. The home page's Invoices button opens CW_BILLING without a patient: LOAD_INVOICES shows the invoices still to be paid. Choosing invoice 3850 (open, 75) coordinates its lines and payments (ON-CLEAR-DETAILS, ON-POPULATE-DETAILS, QUERY_MASTER_DETAILS). A payment of 30 (PAID_ON defaults to today, $$DATE$$) is saved with File > Save, which runs the form's KEY-COMMIT: PRE-INSERT takes the sequence, POST-INSERT sets the invoice PARTIAL, and the list is queried again. Invoice 3852 (partial, 42.50 of 85 paid) gets the remaining 42.50 (a click into a new row lands on its first item, PAID_ON, so AMOUNT is clicked twice): POST-INSERT sets it PAID and the new query no longer lists it. | 466 | 148 | 54 | 0 | 0 | identical |
| billing-return | Clinic > Invoices opens CW_BILLING through the menu (CW_NAV.OPEN_MODULE, OPEN_FORM). CW_BILLING's START_FORM finds no signed-in user and signs in the P_USER default, Front Desk One; the library data is shared, so Clinic > Home shows "Welcome, Front Desk One" and REFRESH_HOME disables the home page's Invoices button. CW_MAIN's menu was set up for the administrator, so Clinic > Invoices still works: it finds CW_BILLING open and goes to it with GO_FORM, and WHEN-FORM-NAVIGATE's LOAD_INVOICES sees the invoices already shown and does nothing. | 192 | 54 | 6 | 0 | 0 | identical |
| billing-unsaved | Leave an invoice with an unsaved payment. Moving to another invoice fires ON-CLEAR-DETAILS: CLEAR_ALL_MASTER_DETAILS finds the changed PAYMENTS block below the master and clears it with ASK_COMMIT; Forms asks whether to save, answered No, and the next invoice's details are queried. | 293 | 92 | 8 | 0 | 0 | identical |
| login-billing | Sign in as BILLING1. APPLY_MENU disables Records > Delete (HAS_ROLE false for ADMIN,RECEPTION) and the home page's Invoices button stays enabled. CW_PATIENTS, opened by OPEN_FORM, does not see the sign-in: START_FORM signs in its P_USER default (title "Front Desk One (Reception)"), so its Invoices... button is disabled for the billing clerk too. | 109 | 6 | 4 | 0 | 0 | identical |
| login-fail | An unknown user. USERNAME validates from its LOV (ValidateFromList), so leaving it opens LOV_USERS with every active user; Escape closes the LOV and Forms refuses the value (FRM-40212). The sign-in never reaches CW_SEC.LOGIN with an unknown name. | 48 | 0 | 4 | 0 | 0 | identical |
| login-lov | Choose the user from the LOV (RG_USERS, active users by full name) and sign in as RECEPTION1. For the RECEPTION role APPLY_MENU disables Clinic > Invoices and REFRESH_HOME disables the Invoices button. CW_PATIENTS, opened by OPEN_FORM, does not see the sign-in in its library data: START_FORM signs in its P_USER default (title "Front Desk One (Reception)") and HAS_ROLE disables Invoices... there. | 111 | 6 | 4 | 0 | 0 | identical |
| login-ok | Sign in as ADMIN: CW_SEC.LOGIN finds the user, NEW_FORM opens CW_MAIN with the shared library data, CW_NAV.START_FORM applies the menu rules (APPLY_MENU: CLINIC.FEES does not exist, nothing is disabled for ADMIN) and sets the title, REFRESH_HOME fills the home page. | 42 | 3 | 3 | 0 | 0 | identical |
| main-about | Help > About runs the menu item's code: MESSAGE with CW_SEC.FULL_NAME. Menu code has its own instance of the attached library's package data, which no sign-in filled, so the name is empty. | 49 | 6 | 5 | 0 | 0 | identical |
| main-print-schedule | Print Schedule runs PRINT_SCHEDULE: a parameter list for today and RUN_REPORT_OBJECT on the report object APPT_SCHEDULE. No Reports server is configured on the host; the scenario records what the runtime does. | 52 | 6 | 4 | 0 | 0 | identical |
| navigation | Move between open forms. Appointments for the first patient; Clinic > Patients goes back to the open CW_PATIENTS and Clinic > Home to CW_MAIN (menu code: CW_NAV.OPEN_MODULE finds the form open and calls GO_FORM); CW_MAIN's WHEN-FORM-NAVIGATE refreshes the home page. The home page's Patients button goes to the open CW_PATIENTS (GO_FORM from form code). Appointments for the second patient goes to the open CW_APPOINTMENTS, whose WHEN-FORM-NAVIGATE (LOAD_PATIENT) loads the new patient: its EXECUTE_QUERY first asks whether to save changes, answered No; the first patient's current appointment is then validated, and CHECK_DOUBLE_BOOKING refuses it, because the seed data has Dr Maya Wilson booked twice at that time. | 835 | 33 | 12 | 0 | 0 | identical |
| patients-find | Search patients. FIND_PATIENTS builds the WHERE clause from the criteria the user filled (name, city, born from, born to), counts the hits (COUNT_QUERY, message level 25) and queries. Moving to another row fires WHEN-NEW-RECORD-INSTANCE, which shows "Patient n of total". | 580 | 27 | 11 | 0 | 0 | identical |
| patients-query | Query by example through the menu module: Records > Enter Query, a last name in the block, Records > Execute Query. File > Exit then closes CW_PATIENTS and returns to the home page. | 317 | 18 | 9 | 0 | 0 | identical |
| total | 8757 | 675 | 209 | 0 | 0 |
The same app with an Angular front end: 22 of 22
The check does not depend on what the new interface is built with. This app has a second front end written in Angular on the same back end and API, and the same scenarios, mapping, tolerance policy and waivers check it: 22 of 22 scenarios at parity, 0 defects, three runs from a fresh database byte-identical, and every diff byte-identical to the default front end's.
| Scenario | match | tolerated | waived | defect | unmapped | Three runs | Diff as the default front end |
|---|---|---|---|---|---|---|---|
| appointments-book | 847 | 28 | 11 | 0 | 0 | identical | identical |
| appointments-cancel | 839 | 27 | 11 | 0 | 0 | identical | identical |
| appointments-delete-refused | 525 | 18 | 8 | 0 | 0 | identical | identical |
| appointments-department | 623 | 32 | 9 | 0 | 0 | identical | identical |
| appointments-double-booking | 838 | 28 | 11 | 0 | 0 | identical | identical |
| appointments-invalid-duration | 839 | 28 | 11 | 0 | 0 | identical | identical |
| appointments-no-patient | 76 | 17 | 4 | 0 | 0 | identical | identical |
| appointments-return | 421 | 15 | 7 | 0 | 0 | identical | identical |
| billing-delete-refused | 190 | 56 | 6 | 0 | 0 | identical | identical |
| billing-patient | 465 | 27 | 7 | 0 | 0 | identical | identical |
| billing-pay | 466 | 148 | 54 | 0 | 0 | identical | identical |
| billing-return | 192 | 54 | 6 | 0 | 0 | identical | identical |
| billing-unsaved | 293 | 92 | 8 | 0 | 0 | identical | identical |
| login-billing | 109 | 6 | 4 | 0 | 0 | identical | identical |
| login-fail | 48 | 0 | 4 | 0 | 0 | identical | identical |
| login-lov | 111 | 6 | 4 | 0 | 0 | identical | identical |
| login-ok | 42 | 3 | 3 | 0 | 0 | identical | identical |
| main-about | 49 | 6 | 5 | 0 | 0 | identical | identical |
| main-print-schedule | 52 | 6 | 4 | 0 | 0 | identical | identical |
| navigation | 835 | 33 | 12 | 0 | 0 | identical | identical |
| patients-find | 580 | 27 | 11 | 0 | 0 | identical | identical |
| patients-query | 317 | 18 | 9 | 0 | 0 | identical | identical |
The app is also rebuilt from native APEX components on its original Oracle schema, checked with the same scenarios: the APEX version.
Faithful to the original
The migrated app copies the original's behaviour, including what looks like a bug. These are the places a visitor will notice.
The interface is new; the behaviour is the original's, and the scenarios check it value by value. Some of that behaviour looks like a bug on a web page. It is kept on purpose, because the point of the demo is that nothing changed:
- No password. The original signs in by user name alone (CW_SEC.LOGIN looks the name up in APP_USERS).
An unknown name opens the list of users, as validation from a list does in Forms; closing the list refuses
the name with
FRM-40212: Invalid value for field. - Everyone becomes Front Desk One once a second module opens. A form opened with OPEN_FORM finds the library's user name empty and signs in its default user, Front Desk One (reception). The library's data is shared, so from then on the header names Front Desk One and the Invoices buttons and menu entries are disabled, whoever signed in.
- Saving one new appointment saves them all. The appointments block's POST-QUERY copies the doctor's department into a base-table item, which marks every queried appointment as changed. A save then updates all of them and runs the double-booking check on each: "7 records applied" for one new appointment.
- The demo data double-books Dr Maya Wilson. Opening that patient's appointments stops at the record the double-booking check refuses, with its message.
- Print schedule fails with FRM-41214: it calls Oracle Reports, which the original's host does not run.
- Oracle message texts on a PostgreSQL app.
FRM-40400: Transaction complete,FRM-40202: Field must be entered,FRM-40350: Query caused no records to be retrievedand the database errors as FRM-40508 to FRM-40510, translated by the library's error handler, are the original's messages. - Invoices cannot be deleted: the invoices block does not allow deletes, so Records > Delete is refused
with
FRM-41049: You cannot delete this record., before the master-detail check could run. - The record counter reads
n/?until the block has fetched its last record, as in Forms.
Five places where the migrated app does not copy the original are proposed as waivers: the frame title before sign-in (C1), the collected-today gauge, which the Forms client exposes no value for (C2), Help > About naming nobody (C3), the home page forgetting the user after a module exits (C4) and the focus after a refused record (C5). A sixth, C6, covers the one place the original loses data: in the billing-pay scenario the original drops a second payment the user entered without saying so; the migrated app saves it.
Coverage of the original
Every trigger and program unit of the Forms modules, measured with Forms Runtime Diagnostics while the
scenarios ran; database PL/SQL measured with DBMS_PLSQL_CODE_COVERAGE.
| Module | Triggers | Program units | Covered | Unreachable | Blocked |
|---|---|---|---|---|---|
| CW_APPOINTMENTS | 9 | 3 | 12 | 0 | 0 |
| CW_BILLING | 10 | 4 | 13 | 1 | 0 |
| CW_LOGIN | 1 | 0 | 1 | 0 | 0 |
| CW_MAIN | 5 | 2 | 7 | 0 | 0 |
| CW_PATIENTS | 5 | 1 | 5 | 1 | 0 |
| CW_APP | 12 | 0 | 12 | 0 | 0 |
| CW_LIB | 13 | 0 | 8 | 5 | 0 |
| total | 55 | 10 | 58 | 7 | 0 |
Decision branches: 30, of which 24 covered, 5 unreachable (retirement candidates) and 1 blocked. Database PL/SQL: 2 unit(s) in the coverage report, 0 of 0 blocks covered. Exit check: PASS.
Every branch with its class
| Trigger or unit | Branch | Class | Scenarios or reason |
|---|---|---|---|
CW_LIB/unit:CW_SEC.ALLOW | role may not use the item - disabled | covered | appointments-book, appointments-cancel, appointments-delete-refused, appointments-department, appointments-double-booking, appointments-invalid-duration, appointments-no-patient, appointments-return, billing-delete-refused, billing-patient, billing-pay, billing-return, billing-unsaved, login-billing, login-lov, navigation, patients-find, patients-query |
CW_LIB/unit:CW_SEC.ALLOW | role may use the item - left enabled | covered | appointments-book, appointments-cancel, appointments-delete-refused, appointments-department, appointments-double-booking, appointments-invalid-duration, appointments-no-patient, appointments-return, billing-delete-refused, billing-patient, billing-pay, billing-return, billing-unsaved, login-billing, login-lov, navigation, patients-find, patients-query |
CW_LIB/unit:CW_SEC.LOGIN | known user - signed in | covered | appointments-book, appointments-cancel, appointments-delete-refused, appointments-department, appointments-double-booking, appointments-invalid-duration, appointments-no-patient, appointments-return, billing-delete-refused, billing-patient, billing-pay, billing-return, billing-unsaved, login-billing, login-lov, login-ok, main-about, main-print-schedule, navigation, patients-find, patients-query |
CW_LIB/unit:CW_SEC.LOGIN | unknown or inactive user - stop alert | unreachable | see CW_LIB/unit:CW_MSG.FAIL |
CW_LIB/unit:CW_NAV.OPEN_MODULE | form not open - OPEN_FORM | covered | appointments-book, appointments-cancel, appointments-delete-refused, appointments-department, appointments-double-booking, appointments-invalid-duration, appointments-return, billing-delete-refused, billing-patient, billing-pay, billing-unsaved, login-billing, login-lov, navigation, patients-find, patients-query |
CW_LIB/unit:CW_NAV.OPEN_MODULE | form open - GO_FORM | covered | navigation |
CW_LIB/unit:CW_ERR.ON_ERROR | check constraint APPOINTMENTS_DUR_CK - translated | covered | appointments-invalid-duration |
CW_LIB/unit:CW_ERR.ON_ERROR | child records (ORA-02292) - translated | covered | appointments-delete-refused |
CW_LIB/unit:CW_ERR.ON_ERROR | other error - Forms' own message | covered | billing-delete-refused |
CW_LIB/unit:CW_ERR.ON_ERROR | duplicate key (ORA-00001) - translated | unreachable | Every key the forms insert comes from a sequence in PRE-INSERT (APPOINTMENTS_SEQ, PAYMENTS_SEQ). |
CW_LIB/unit:CW_ERR.ON_ERROR | NOT NULL column (ORA-01400) - translated | unreachable | Every NOT NULL column the forms insert is a Required item (FRM-40202 first), has an initial value or is set in PRE-INSERT. |
CW_LIB/unit:CW_ERR.ON_ERROR | APPOINTMENTS_PATIENT_FK or APPOINTMENTS_DOCTOR_FK - translated | unreachable | PATIENT_ID comes from CTL.PATIENT_ID (a queried patient) and DOCTOR_ID from LOV_DOCTORS; neither is typed, and the forms delete no patient or doctor. |
CW_APPOINTMENTS/unit:CHECK_DOUBLE_BOOKING | overlap - refused | covered | appointments-double-booking, navigation |
CW_APPOINTMENTS/unit:CHECK_DOUBLE_BOOKING | no overlap or cancelled - accepted | covered | appointments-book, appointments-cancel, appointments-delete-refused, appointments-department, appointments-double-booking, appointments-invalid-duration, appointments-return, billing-patient, navigation |
CW_APPOINTMENTS/unit:LOAD_PATIENT | no patient chosen - message | covered | appointments-no-patient |
CW_APPOINTMENTS/unit:LOAD_PATIENT | another patient - query | covered | appointments-book, appointments-cancel, appointments-delete-refused, appointments-department, appointments-double-booking, appointments-invalid-duration, appointments-return, billing-patient, navigation |
CW_APPOINTMENTS/unit:LOAD_PATIENT | same patient - nothing | covered | appointments-return |
CW_BILLING/unit:LOAD_INVOICES | no patient - invoices to be paid | covered | billing-delete-refused, billing-pay, billing-return, billing-unsaved |
CW_BILLING/unit:LOAD_INVOICES | already showing - nothing | covered | billing-return |
CW_BILLING/unit:LOAD_INVOICES | a patient - that patient's invoices | covered | billing-patient |
CW_BILLING/KEY-COMMIT | saved - requery and message | covered | billing-pay |
CW_BILLING/KEY-COMMIT | not saved - no message | covered | billing-pay |
CW_MAIN/unit:PRINT_SCHEDULE | report finished | blocked | Needs Oracle Reports: the PoC host runs Forms without a Reports server, so RUN_REPORT_OBJECT fails (FRM-41214) and the job never finishes. Missing resource, not a harness limit. |
CW_MAIN/unit:PRINT_SCHEDULE | report not finished | covered | main-print-schedule |
CW_BILLING/unit:QUERY_MASTER_DETAILS | immediate relation - detail queried | covered | billing-delete-refused, billing-patient, billing-pay, billing-return, billing-unsaved |
CW_BILLING/unit:QUERY_MASTER_DETAILS | deferred relation | unreachable | Both relations of INVOICES (INVOICES_LINES, INVOICES_PAYMENTS) have Deferred No. |
CW_BILLING/unit:CLEAR_ALL_MASTER_DETAILS | unchanged details - CLEAR_BLOCK(NO_VALIDATE) | covered | billing-delete-refused, billing-pay, billing-unsaved |
CW_BILLING/unit:CLEAR_ALL_MASTER_DETAILS | changed details - CLEAR_BLOCK(ASK_COMMIT) | covered | billing-unsaved |
CW_PATIENTS/unit:FIND_PATIENTS | no search fields - every patient | covered | appointments-book, appointments-cancel, appointments-delete-refused, appointments-department, appointments-double-booking, appointments-invalid-duration, appointments-return, billing-patient, login-billing, login-lov, navigation, patients-find, patients-query |
CW_PATIENTS/unit:FIND_PATIENTS | search fields filled - filtered | covered | patients-find |
Database PL/SQL units
| Unit | Type | Blocks | Covered | Class |
|---|---|---|---|---|
| CW_API | PACKAGE BODY | None | 0 | unreachable |
| CW_FEE_API | PACKAGE BODY | None | 0 | unreachable |
Waivers
Source behaviour a customer would probably not replicate, proposed for the customer's decision. Each is pinned to the exact values it covers; the counts are values waived in the final diffs. File: waivers.yaml.
Waived: 6 waivers are proposed for the customer's decision; 6 of them cover 209 values here, where the migrated app deliberately does not copy the original (see waivers).
| Id | Waiver | Values | Reason |
|---|---|---|---|
| C1 | Oracle's frame title before sign-in | 46 | Until CW_NAV.START_FORM sets the MDI title, the Forms frame shows the runtime's own title "Oracle Fusion Middleware Forms Services". The target's frame reads "CareWell Clinic" from the start: the web page is the clinic's application, not Oracle's runtime. From sign-in on, both show the same title. |
| C2 | The home page's collected-today gauge reads empty | 118 | HOME.COLLECTED is a display item drawn as a half gauge on the original canvas; the Forms client's component tree exposes no text for it, so the source records '' at every step. The target shows the amount REFRESH_HOME computes (the same query as the source), as a number with a bar. |
| C3 | Help > About names nobody | 1 | The menu module CW_APP runs its code with its own instance of the library CW_LIB, whose package data nobody signed into, so Help > About reads "CareWell Clinic, signed in as ." for every user. The target names the signed-in user, which is what the menu code asks for (cw_sec.full_name). |
| C4 | The home page forgets the user after File > Exit of a module | 1 | CW_PATIENTS, opened with OPEN_FORM after the NEW_FORM from CW_LOGIN, signs in its own library instance (P_USER); when it exits, CW_MAIN's WHEN-FORM-NAVIGATE (REFRESH_HOME) finds the library's package data empty and shows "Welcome," without a name. The target keeps the signed-in user's name on the home page. |
| C5 | No item has the focus after a fetched record is refused | 1 | When LOAD_PATIENT's query fetches an appointment that CHECK_DOUBLE_BOOKING refuses (the seed data books Dr Maya Wilson twice at one time), the Forms client leaves the keyboard focus on the block's scroll area rather than on an item. The target fetches, refuses and stops at the same record, with the same message and record count, and keeps the cursor in the first item of the first record, where typing goes. |
| C6 | The second payment of billing-pay is lost | 42 | In billing-pay, after the 42.50 is typed into the new payment row and Tab leaves AMOUNT, the Forms client reports "Amount Required 42.50" on the message line, and File > Save then shows the alert "FRM-40401: No changes to save." (record indicator 0/1). PRE-INSERT has drawn PAYMENTS_SEQ (the source draws 6733 and 6734, as the target does), yet nothing is saved: payment 6734 is not in PAYMENTS and invoice 3852 stays PARTIAL, while the screen still shows the unsaved payment. Identical in all three runs. The target saves the payment as the form's code says: POST-INSERT sets invoice 3852 PAID, KEY-COMMIT queries the invoices to be paid again (3852 is no longer among them) and shows "Saved. Invoice 3852 is PAID.". Replicating would mean losing a payment the user entered. |