FormsRefresh

Home / Demo

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 Same app, Angular front end Scenarios and diffs Faithful to the original

Target: .NET 10 (ASP.NET Core minimal API) and PostgreSQL, a single-page web client. Original Forms source: github.com/v7med7elmy-ai/oracle-retail-management-system at commit 30b5409, licence: MIT.

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: 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

The same app with an Angular front end: 17 of 17

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: 17 of 17 scenarios at parity, 0 defects, three runs from a fresh database byte-identical, and every diff byte-identical to the default front end's.

ScenariomatchtoleratedwaiveddefectunmappedThree runsDiff as the default front end
categories-add-delete6400012identicalidentical
categories-browse5700014identicalidentical
customers-add-delete6840012identicalidentical
customers-browse6200014identicalidentical
employees-add-delete7840012identicalidentical
employees-browse6660015identicalidentical
main-menu-exit220004identicalidentical
main-menu-orders34270011identicalidentical
order-two-lines2592900099identicalidentical
orders-add-new1152160062identicalidentical
orders-browse1181700051identicalidentical
orders-delete-empty971230037identicalidentical
orders-delete-refused911200039identicalidentical
orders-navigate-unsaved1401890062identicalidentical
orders-save-fails1351940060identicalidentical
products-add-delete10280017identicalidentical
products-browse62100014identicalidentical

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 migrated app has a new interface, but its behaviour is the original's, recorded scenario by scenario. Where the original does something odd, the migrated app does it too, so the diff stays at zero defects. Each waiver (W1-W10) names a behaviour the customer can choose to drop; until they do, it stays. In the app, a grey note under the message line or the alert explains these when they appear.

What you see Why Waiver
"FRM-41003: This function cannot be performed here." when the app starts The original's main menu runs a built-in in its startup trigger that fails there. W8
Orders opens on a blank new order with a number (16), and the first Query / reload asks "Do you want to save the changes you have made?" The original creates a record and draws an order number when the form opens. Yes saves a blank order; No discards it. W2
An order saved from that record gets the next number (17), not the one shown The original draws a second number when it inserts. W2
New orders are saved without an order date The original inserts the empty date item as NULL. W1
Two alerts after every order save: "Saved." and then تم حفظ الأوردر بنجاح يا بطل! ("The order was saved successfully, hero!") The commit confirmation and the form's own success message, each a modal alert in the original. A failed save shows حصل مشكلة في الحفظ، اتأكد من البيانات ("A problem occurred while saving, check the data"). W4
"Add new" on Orders can never be saved (FRM-40202, then FRM-40222) The added record has no number, and the original's order id is required but disabled. Enter new orders in the record the form opens on. W10
Order lines need a typed Item id, and ids are unique across all orders The original has the user type the line key and draws none from its sequence. W3
"Customer Id1" on the message line after a query in Orders A debug message left in a trigger: the first order's customer. W6
"Category Id Required902" (or Customer, Employee, Product) after Next, Previous or Last A debug message left in a trigger: the record's key appended to fixed text. W5
"Press Tab to move between choices, Return to select." while the save question is open The Forms Java client's keyboard hint for its dialogs. W9
The alert "gooooooooooooooooooooood" when leaving Employees A developer's placeholder alert on the exit button. W7
Errors read "FRM-40508: ORACLE error: unable to INSERT record." (or UPDATE, DELETE), also against PostgreSQL The original's wording, kept because the scenarios compare it. The migrated app adds one line under it with the reason (for example "Price must be a number"). -
Typed primary keys in Categories, Customers, Employees and Products The original has the user type each key. -
Delete commits at once, without asking The original's delete button deletes and commits. -
Exit from Orders drops unsaved order lines without asking The original leaves the form without validating (EXIT_FORM NO_VALIDATE). -
Total amount and Final amount stay empty after lines are added The original never computes them; only each line's total is computed. -
The order type list offers "sala" A list value of the original. -
A message stays on the message line while you type The Forms message line keeps its last message until the next one. -

What is new rather than copied: the layout, the menu, the dialogs, the names shown next to customer, employee, product and category ids, the reason line under database errors, Return moving to the next field instead of saving, and the page shown after Exit. A form opened from the menu shows the trail "Main menu > Customers" and the suspended menu under it, as the original's CALL_FORM leaves the menu waiting; its Exit button reads "Back to menu", and the browser's Back runs the same Exit, save question included.

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.

Waived 0 everywhere: 10 waivers are proposed, but the migrated app implements every one of those source behaviours, so no value needs a waiver. Each stays available if the customer prefers the modern behaviour (see waivers).

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.