Oman broker renewal & resubmission
The Oman broker pre-registration flow ends the moment the CRM
callback mints a real Broker and the application lands in ACTIVE with broker_id set. This
page picks up from there. An onboarded Oman broker still owns the same
OmanPreRegistrationBrokerApplication row, and that row keeps living: a company broker’s contract
expires once a year, the broker resubmits signed contracts to renew, and any single document an
admin rejects can be re-uploaded for a fresh review. Everything here is verified against the current
backend (develop @ 8434e475).
The post-approval state machine
Section titled “The post-approval state machine”The onboarding spine parks the row in ACTIVE. From there, three of the twelve
OmanBrokerApplicationStatusEnums states (OmanBrokerApplicationStatusEnums.php:11-22) run the
lifecycle: PENDING_RENEWAL (:20), CONTRACT_EXPIRED (:21), and
PENDING_DOCUMENT_REVIEW (:22). All three are in the Voyager dashboard filter
(getValidStatusForDashboard, :47-60), so they surface as admin tasks just like the onboarding
review states do.
stateDiagram-v2 [*] --> ACTIVE: onboarded (CRM callback minted the Broker) ACTIVE --> CONTRACT_EXPIRED: scheduled daily job when contract_end_date is past (company brokers only) ACTIVE --> PENDING_RENEWAL: broker resubmit-contract with both signed contracts present ACTIVE --> PENDING_DOCUMENT_REVIEW: broker resubmit-document (a rejected non-contract doc) CONTRACT_EXPIRED --> PENDING_RENEWAL: broker resubmit-contract with both signed contracts present CONTRACT_EXPIRED --> PENDING_DOCUMENT_REVIEW: broker resubmit-document PENDING_RENEWAL --> ACTIVE: admin approve-renewal when every document is accepted then CRM update job PENDING_RENEWAL --> CONTRACT_SENT: admin reject-renewal when a signed contract is rejected CONTRACT_SENT --> PENDING_RENEWAL: broker re-uploads both signed contracts PENDING_DOCUMENT_REVIEW --> ACTIVE: admin approve-documents-after-review PENDING_DOCUMENT_REVIEW --> MISSING_INFORMATION: admin reject-documents-after-review MISSING_INFORMATION --> PENDING_DOCUMENT_REVIEW: broker resubmit-document
Contract expiry — a scheduled job, company brokers only
Section titled “Contract expiry — a scheduled job, company brokers only”Expiry is not a user action. App\Console\Kernel.php:45 schedules
oman-broker-with-contract-expired:notify daily; the command
(NotifyOmanContractExpired.php:10,17) dispatches
NotifyOmanBrokerWithContractExpiredJob, which does the transition.
-
Who it selects. Only applications that are
ACTIVE, have a non-nullcontract_end_datestrictly before today, and whose broker is a company type (local_company/international_company) —getBrokerApplicationsQuery,NotifyOmanBrokerWithContractExpiredJob.php:89-104. Individual ambassadors have no contract, so this job never touches them — an ambassador’s row simply staysACTIVE. -
The atomic flip. Per broker it runs a single guarded
update— it only fires whenlast_notified_atis null or older than today, and in that one statement it setslast_notified_at = nowandstatus = CONTRACT_EXPIRED(:57-71). Thatlast_notified_atguard is what makes the daily run idempotent and race-safe: a second worker on the same row gets0 rows updatedand returns. -
Documents expire too. The signed-contract documents (Salalah-Beach + Jebel-Sifah) are bulk-set to
document_status = EXPIRED(:73-78), so the broker must upload fresh signed contracts to renew. -
Notifications. The broker gets
BrokerContractExpiredNotification; each configured admin getsAdminBrokerContractExpiredEmail(:80-86). Admin recipients come fromomanBrokerApplicationNotification.admin_emails(envOMAN_CONTRACT_EXPIRED_ADMIN_EMAILS); if it’s empty the job logs a warning but still expires the row and still notifies the broker (:36-39).
Broker resubmission endpoints
Section titled “Broker resubmission endpoints”Both resubmit endpoints save the uploaded file first (via SaveDocument, with
markPendingAndClearReview = true, so the touched document is reset to PENDING with its rejection
reason and admin comment cleared — SaveDocument.php:19-43, UpdateBrokerPreRegistrationDocument.php:40-46),
then run their status action. If the broker has no application row, both return 404
pre_registration_application_not_found.
-
Renew the contract —
POST oman-application/resubmit-contract(OmanRegistrationApplicationController@resubmitApplication,routes/api/broker.php:280). Acceptsjebel_sifah_signed_contract_fileand/orsalalah_beach_signed_contract_file(each nullable,max:5120KB,mimes:jpg,jpeg,png,pdf,doc,docx—ResubmitBrokerApplicationRequest). The actionResubmitApplication.handleis valid fromCONTRACT_EXPIRED,CONTRACT_SENT,ACTIVE,PENDING_RENEWAL, orPENDING_DOCUMENT_REVIEW(else 422resubmit_application_wrong_status,ResubmitApplication.php:18-35). It moves the row toPENDING_RENEWALonly when both signed contracts now exist with statusPENDINGorACCEPTED(count() === 2,:37-45). Upload only one and it silently stays put. -
Resubmit a rejected document —
POST oman-application/resubmit-document(@resubmitDocument,routes/api/broker.php:281). Accepts a singlefile+document_type, wheredocument_typemust be invaluesExceptSignedContract()— i.e. any document except the two signed contracts (ResubmitBrokerApplicationDocumentRequest; signed contracts go through step 1). The actionResubmitDocument.handleis valid fromMISSING_INFORMATION,CONTRACT_EXPIRED,CONTRACT_SENT,PENDING_DOCUMENT_REVIEW,ACTIVE, orPENDING_RENEWAL(else 422resubmit_documents_wrong_status,ResubmitDocument.php:16-35). It moves the row toPENDING_DOCUMENT_REVIEWand emails the admins (AdminBrokerDocumentsResubmittedEmail,:46-64) — unless the row is alreadyPENDING_DOCUMENT_REVIEWorPENDING_RENEWAL, in which case the file is replaced but no status change and no admin email happen (:38-44). -
Read / upload supporting documents.
GET oman-application/documentslists the row’s documents (OmanApplicationDocumentController@index,broker.php:275);POST oman-application/documentsuploads one (@save,broker.php:279);GET oman-application/documents/{document}streams a file, guarded so a broker can only download their own application’s documents (else 403/404,OmanApplicationDocumentController.php:80-98).
ODH admin review, in Voyager
Section titled “ODH admin review, in Voyager”The renewal and document-review decisions are admin actions under routes/web/dashboard.php (behind
admin.user), handled by OmanPreRegistrationBrokerApplicationController.
| Admin action (route) | Guard | Effect | Action class |
|---|---|---|---|
approve-renewal (dashboard.php:92) |
only from PENDING_RENEWAL, requires signed docs present and every document accepted |
→ ACTIVE, sets contract_start_date = now + contract_end_date = now + 1yr, clears comment/reason, dispatches the CRM update job |
ApproveApplicationRenewal.php:17-54 |
reject-renewal (dashboard.php:97) |
only from PENDING_RENEWAL, requires at least one rejected signed contract |
→ CONTRACT_SENT, notifies BrokerRejectedContractRenewalNotification |
RejectApplicationRenewal.php:17-49 |
approve-documents-after-review (dashboard.php:102) |
no status guard | → ACTIVE, clears comment/reason, notifies BrokerDocumentsAcceptedAfterReviewNotification |
ApproveDocumentsAfterDocumentReview.php:11-25 |
reject-documents-after-review (dashboard.php:107) |
— | → MISSING_INFORMATION + admin_comment, notifies BrokerApplicationDocumentReviewMissingInformationNotification |
RejectDocumentsAfterDocumentReview.php:11-27 |
per-doc status / bulk-accept / download (dashboard.php:112-124) |
— | set an individual document to accepted / rejected / expired |
OmanPreRegistrationBrokerDocumentController |
sequenceDiagram participant BR as Broker (real broker token) participant APP as Application row participant AD as ODH admin (Voyager) participant JOB as UpdateOmanPreRegistrationBrokerInCrmJob participant MW as crms-middleware then CRM BR->>APP: resubmit-contract (upload both signed contracts) Note over APP: both signed docs PENDING or ACCEPTED so status becomes PENDING_RENEWAL AD->>APP: approve-renewal (needs every document accepted) Note over APP: status ACTIVE, contract_start now, contract_end now plus one year APP->>JOB: dispatch (idempotent per application via WithoutOverlapping) JOB->>MW: PATCH oman-pre-registration brokers with header country oman MW-->>JOB: 200 JOB->>BR: BrokerContractRenewedNotification
Status reference — the renewal & expiry states
Section titled “Status reference — the renewal & expiry states”From OmanBrokerApplicationStatusEnums.php:11-22 (the three onboarding-only draft states are covered on
the pre-registration page).
| Status (value) | What it means | How you get here | How you leave |
|---|---|---|---|
active |
Fully onboarded / renewed. A company broker’s contract_end_date is in the future |
CRM callback (onboarding), approve-renewal, or approve-documents-after-review |
Contract expires, or the broker resubmits a contract/document |
pending_renewal |
Fresh signed contracts uploaded, awaiting admin renewal decision | Broker resubmit-contract with both signed contracts present |
approve-renewal → active, or reject-renewal → contract_sent |
contract_expired |
Yearly agreement lapsed. Signed-contract docs are set to expired |
Scheduled daily job when contract_end_date is past (company brokers only) |
Broker resubmit-contract → pending_renewal, or resubmit-document → pending_document_review |
pending_document_review |
A resubmitted non-contract document is awaiting admin review | Broker resubmit-document |
approve-documents-after-review → active, or reject-documents-after-review → missing_information |
contract_sent |
Renewal rejected — broker must upload fresh signed contracts (also an onboarding state) | reject-renewal (renewal path) |
Broker resubmit-contract → pending_renewal |
missing_information |
Document review found problems — broker must fix a document (also an onboarding state) | reject-documents-after-review |
Broker resubmit-document → pending_document_review |
Document status reference
Section titled “Document status reference”Each OmanPreRegistrationBrokerDocument.document_status is one of four values
(OmanBrokerApplicationDocumentStatusEnums.php:11-14). The last three are the admin-settable ones
(getUpdateStatusActions, :16-23).
| Document status | Meaning |
|---|---|
pending |
Uploaded / resubmitted, awaiting an admin decision. A resubmit resets the document to this and clears its prior rejection reason + admin comment |
accepted |
Admin approved this document. Renewal approval requires every document to be accepted |
rejected |
Admin rejected it (with a reason + optional comment). The broker re-uploads via resubmit-contract or resubmit-document |
expired |
Set on the signed-contract documents when the yearly job flips the application to contract_expired |
