# Purchase Order Reference
Use the current purchase order approval as the canonical code-first example.
## Main Files
- Entity: `forge-server/forge-business/forge-business-core/src/main/java/com/mdframe/forge/business/core/purchase/domain/SamplePurchaseOrder.java`
- Controller: `.../purchase/controller/SamplePurchaseOrderController.java`
- Service: `.../purchase/service/impl/SamplePurchaseOrderServiceImpl.java`
- Flow constants: `.../purchase/support/SamplePurchaseOrderFlowDefinition.java`
- BPMN builder: `.../purchase/support/SamplePurchaseOrderFlowBpmn.java`
- Provider: `.../purchase/provider/SamplePurchaseOrderCodeFormProvider.java`
- Mapper XML: `forge-server/forge-business/forge-business-core/src/main/resources/mapper/business/SamplePurchaseOrderMapper.xml`
- Frontend API: `forge-admin-ui/src/api/business/purchase-order-test.js`
- Frontend page/form: `forge-admin-ui/src/views/business/purchase-order-test.vue`
- Table/dict/menu seed: `forge-server/db/migration/V1.0.81__add_sample_purchase_order_flow_test.sql`
- Flow binding seed: `forge-server/db/migration/V1.0.82__seed_sample_purchase_order_flow_binding.sql`
- App Center seed: `forge-server/db/migration/V1.0.83__seed_sample_purchase_order_app_center_entry.sql`
- Fallback node permission patch: `forge-server/db/migration/V1.0.84__extend_sample_purchase_order_form_asset_fields.sql`
## Business Contract
- Object code/business type: `sample_purchase_order`
- Flow model key: `sample_purchase_order_approval`
- Provider key: `samplePurchaseOrder`
- Form key: `sample_purchase_order_approval_form`
- Form mode: `BUSINESS_CODE_FORM`
- Business key: `sample_purchase_order:{id}`
## Node Keys
- `dept_leader_approve`: department leader approval.
- `engineering_manager_approve`: engineering manager approval.
- `purchase_countersign`: parallel multi-instance countersign.
- `applicant_modify`: applicant modifies and resubmits or terminates.
## Variables
Start variables include:
- `businessKey`
- `objectCode`
- `recordId`
- `purchaseOrderId`
- `orderNo`
- `title`
- `amountCent`
- `initiator`
- `deptLeaderId`
- `engineeringManagerId`
- `countersignUserList`
- `ccRoleKeys`
Task completion variables used by gateways/status:
- `approvalResult`: `approve` or `reject`
- `approved`: boolean; countersign completion uses false to stop early on rejection
## Status Behavior
- New record: `DRAFT`.
- Submit: start Flowable, write `business_key/process_instance_id`, set `IN_PROCESS`.
- Reject from approval/countersign: set `NEED_MODIFY`.
- Applicant modify approve/resubmit: set `IN_PROCESS`.
- Applicant modify reject/terminate: set `REJECTED`.
- Process completed: set `APPROVED`.
- Process canceled: set `CANCELED`.
The sample also repairs drift:
- `TASK_CREATED` for `applicant_modify` repairs `IN_PROCESS -> NEED_MODIFY`.
- `TASK_CREATED` for approval nodes repairs `NEED_MODIFY -> IN_PROCESS`.
- Task save methods repair the same transitions before validating.
- Page/detail queries reconcile running status by reading active `sys_flow_task.task_def_key`.
## Form Integration
`SamplePurchaseOrderCodeFormProvider` registers a code form asset with:
- `formKey`
- `formName`
- `formMode=BUSINESS_CODE_FORM`
- `providerKey`
- `formUrl`
- `fields` / `fieldCatalog`
- `supportsSave=true`
`buildContext` loads business record detail and returns `BusinessTaskFormContextVO`. `saveContext` converts platform payload into `SamplePurchaseOrderTaskSaveDTO`, then calls `saveTaskFields`.
## BPMN Pattern
The BPMN user tasks set:
- `flowable:assignee="${deptLeaderId}"` style variable expressions.
- `flowable:formKey="sample_purchase_order_approval_form"`.
- `flowable:formFieldPermissions='[...]'`.
- Approval button flags such as `flowable:allowApprove`, `flowable:allowReject`, `flowable:allowDelegate`, `flowable:requireComment`.
Gateways use reject conditions:
```xml
```
Countersign uses:
```xml
```
## Initialization Rule
`ensureFlowModel()` may create a default model when absent or when existing BPMN XML is empty. It must not overwrite existing non-empty BPMN XML, because the flow designer is the owner of node form permissions and approval settings after users save the model.