FormsRefresh

Retail order system

Six Forms modules: a main menu, ORDERS (master-detail with a list of values and alerts) and four single-table forms (categories, customers, employees, products).

Open the live migrated app Target: .NET 10 (ASP.NET Core minimal API) and PostgreSQL, a single-page web client.

The live demos share one database per app: visitors see each other's changes, and the data resets to the scenario fixture every night.

Original Forms source: github.com/v7med7elmy-ai/oracle-retail-management-system at commit 30b5409, MIT licence.

Parity: 17 of 17 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.

ScenarioWhat it doesmatchtoleratedwaiveddefectunmappedThree runs
categories-add-deleteAdd a record, save, delete the unreferenced fixture record.6400012identical
categories-browseOpen categories from the main menu, browse first/last/next/previous, exit to the menu.5700014identical
customers-add-deleteAdd a record, save, delete the unreferenced fixture record.6840012identical
customers-browseOpen customers from the main menu, browse first/last/next/previous, exit to the menu.6200014identical
employees-add-deleteAdd a record, save, delete the unreferenced fixture record.7840012identical
employees-browseOpen employees from the main menu, browse first/last/next/previous, exit to the menu.6660015identical
main-menu-exitPress the main menu's exit button.220004identical
main-menu-ordersOpen orders from the main menu, exit back to the menu.34270011identical
order-two-linesCreate an order with two lines, change a quantity, save.2592900099identical
orders-add-newQuery the orders, press ADD NEW, fill a header and save; ORDER_ID is mandatory and empty, so the save stops.1152160062identical
orders-browseExecute the query, decline to save the PRE-FORM record, browse the orders and their lines.1181700051identical
orders-delete-emptyQuery the orders, go to order 902 (no lines), press DELETE; the order is deleted.971230037identical
orders-delete-refusedQuery the orders, press DELETE on order 901, which has lines; nothing is deleted.911200039identical
orders-navigate-unsavedQuery, change a line quantity, press Next; Cancel, then Next again and No.1401890062identical
orders-save-failsEnter an order with a line whose ITEM_ID already exists, press SAVE; the commit fails.1351940060identical
products-add-deleteAdd a record, save, delete the unreferenced fixture record.10280017identical
products-browseOpen products from the main menu, browse first/last/next/previous, exit to the menu.62100014identical
total1570136100535

Tolerance policy: tolerance-policy.yaml.

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.

ModuleTriggersProgram unitsCoveredUnreachableBlocked
MAIN_MENU70700
ORDERS1431700
CATEGORIES_FORM90900
CUSTOMERS_FORM90900
EMPLOYEES_FORM90900
PRODUCT_FORM90900
total5736000

Decision branches: 18, of which 14 covered, 2 unreachable (retirement candidates) and 2 blocked. Database PL/SQL: 1 unit(s) in the coverage report, 1 of 1 blocks covered. Exit check: PASS.

Every branch with its class
Trigger or unitBranchClassScenarios or reason
ORDERS/ORDERS.PUSH_BUTTON10/WHEN-BUTTON-PRESSEDcommit succeeded (FORM_SUCCESS TRUE)coveredorder-two-lines
ORDERS/ORDERS.PUSH_BUTTON10/WHEN-BUTTON-PRESSEDcommit failed (FORM_SUCCESS FALSE)coveredorders-add-new, orders-save-fails
ORDERS/ORDERS/ON-CHECK-DELETE-MASTERdetail rows exist, delete refusedcoveredorders-delete-refused
ORDERS/ORDERS/ON-CHECK-DELETE-MASTERno detail rows, delete goes aheadcoveredorders-delete-empty
ORDERS/ORDERS/ON-POPULATE-DETAILSmaster record NEW or INSERT (or ORDER_ID null) - no detail querycoveredorders-add-new
ORDERS/ORDERS/ON-POPULATE-DETAILSdetail queriedcoveredorders-add-new, orders-browse, orders-delete-empty, orders-delete-refused, orders-navigate-unsaved
ORDERS/ORDERS/ON-POPULATE-DETAILScursor moved by the query, returned to the start itemcoveredorders-add-new, orders-browse, orders-delete-empty, orders-delete-refused, orders-navigate-unsaved
ORDERS/ORDERS/ON-POPULATE-DETAILScursor still on the start item after the queryunreachableThe relation is not deferred, so QUERY_MASTER_DETAILS always does GO_BLOCK('ORDER_ITEMS') and the cursor always leaves the master item it started on.
ORDERS/unit:QUERY_MASTER_DETAILSrelation not deferred - GO_BLOCK and EXECUTE_QUERYcoveredorders-add-new, orders-browse, orders-delete-empty, orders-delete-refused, orders-navigate-unsaved
ORDERS/unit:QUERY_MASTER_DETAILSrelation deferred - SET_BLOCK_PROPERTY non-coordinatedunreachableThe only relation (ORDERS_ORDER_ITEMS) is not deferred and nothing changes that at run time.
ORDERS/unit:QUERY_MASTER_DETAILSGO_BLOCK to the detail failed - exception handlerblockedNeeds GO_BLOCK('ORDER_ITEMS') to fail during master coordination. The block has no PRE-BLOCK, WHEN-NEW-BLOCK-INSTANCE or record-level validation that can refuse entry, and the master record was validated before coordination began; no input found that makes it fail. FRD would show it as CHECK_PACKAGE_FAILURE with FORM_SUCCESS FALSE.
ORDERS/unit:CHECK_PACKAGE_FAILUREprevious built-in succeededcoveredorders-add-new, orders-browse, orders-delete-empty, orders-delete-refused, orders-navigate-unsaved
ORDERS/unit:CHECK_PACKAGE_FAILUREprevious built-in failed - raise FORM_TRIGGER_FAILUREblockedCalled after GO_BLOCK and GO_ITEM in the relation code. Needs one of those navigations to fail, the same condition as the QUERY_MASTER_DETAILS exception branch; no input found.
ORDERS/unit:CLEAR_ALL_MASTER_DETAILSdetail block NEW - nothing to clearcoveredorders-add-new, orders-browse, orders-delete-empty, orders-delete-refused, orders-navigate-unsaved
ORDERS/unit:CLEAR_ALL_MASTER_DETAILSdetail block queried - CLEAR_BLOCK(NO_VALIDATE), cursor returnedcoveredorders-add-new, orders-browse, orders-delete-empty
ORDERS/unit:CLEAR_ALL_MASTER_DETAILSchanged block below the master found (First_Changed_Block_Below)coveredorders-navigate-unsaved
ORDERS/unit:CLEAR_ALL_MASTER_DETAILSchanges - CLEAR_BLOCK(ASK_COMMIT), user discards or saves, detail clearedcoveredorders-navigate-unsaved
ORDERS/unit:CLEAR_ALL_MASTER_DETAILSchanges - CLEAR_BLOCK(ASK_COMMIT), user cancels, FORM_TRIGGER_FAILURE, cursor returnedcoveredorders-navigate-unsaved
Database PL/SQL units
UnitTypeBlocksCoveredClass
TRG_CALC_ITEM_TOTALTRIGGER11covered

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.

Each waiver applies to 0 values: the migrated app implements the source behaviour, so the customer can still choose either way.

IdWaiverValuesReason
W1ORDER_DATA saved as NULL0The source saves a new order without an order date: the empty ORDER_DATA item is inserted as NULL, so no order the form creates has a date. A target that stores the time of the order instead keeps data the source loses. Parity is implemented (the target sends every empty header item as NULL).
W2Order number consumed when the form opens0Opening ORDERS draws an order number from ORD_SEQ and shows it (16); saving draws another one and stores that (17). The number the user sees while entering the order is not the number of the saved order, and every opened form uses up a number. A target that assigns the number at save draws one value per order and shows it only after saving. Parity is implemented (the target draws a number on opening, shows it, and lets the insert draw the stored one).
W3Line ITEM_ID typed by the user0The user types the key of each order line (ITEM_ID 1, 2), and ITEM_SEQ is not used. ITEM_ID is the primary key of all order lines, not a line number within the order, so a second order whose lines are typed as 1 and 2 again fails on a duplicate key. A target that draws the key from ITEM_SEQ avoids the collision. Parity is implemented (new lines take the typed key; a key that belongs to another order is refused).
W4Two modal alerts after saving0After a save the source shows two modal alerts, each needing OK: the commit confirmation (FRM-40400, "3 records applied and saved") and then the form's own success message. A web target would normally confirm once, without a modal dialog, in the status line. Parity is implemented (the target shows the two confirmations as browser alerts, in the same order, with the same messages in the status line).
W5Key debug message on record navigation (single-table forms)0Next, Previous and Last in Categories, Customers, Employees and Products leave a message such as "Category Id Required902" on the message line: the record's key appended to a fixed text, left over from a validation trigger. It tells the user nothing (no field is required at that point) and First does not show it. A target would show no message. Parity is implemented (the same text on the same buttons).
W6Customer debug message in ORDERS0After a query in ORDERS the message line reads "Customer Id1": the first order's customer number appended to a fixed text, left over from a trigger, and it stays while the user navigates. A target would show no message. Parity is implemented.
W7Placeholder alert on leaving Employees0The Employees exit button shows a modal alert "gooooooooooooooooooooood" that must be acknowledged before the form closes: a developer's placeholder. A target would close the form directly. Parity is implemented. Without the alert the scenario's acknowledging step cannot be performed; that entry stays a defect to review with this waiver (it names no value to pin).
W8Error message when the application starts0The main menu opens with "FRM-41003: This function cannot be performed here." on the message line: a built-in started from the menu's startup trigger fails in that context. The user did nothing wrong; a target would start with an empty message line. Parity is implemented.
W9Keyboard hint of the Forms client while a question is open0While the save question (Yes/No/Cancel) is open, the Forms Java client writes its keyboard hint "Press Tab to move between choices, Return to select." to the message line. It belongs to the client's dialog handling, not to the application. A web target's dialog needs no such hint. Parity is implemented (the target writes the same hint while its question dialog is open).
W10An order added with Add cannot be saved0Add in ORDERS creates a record without an order number. ORDER_ID is required and disabled, so the user cannot enter one and saving fails every time: "FRM-40202: Field must be entered.", then "FRM-40222: Disabled item 'ORDERS.ORDER_ID' failed validation.", then the form's own failure message. Only the record the form opens on (which draws a number) can be saved. A target would number the added order and save it. Parity is implemented. A target that saves it also differs in the database rows and ORD_SEQ draws of that save; those entries are reviewed with this waiver, not covered by it.