This is the SRD for Assignment 3 (lesson C4). The CanalBox endpoints already exist on staging; you use them, you do not build them. Everything you need to configure is on this page. If something is not written here, the answer is "not required"; do not invent it.
| Item | Value |
|---|---|
| Partner | CanalBox (internet provider) |
| Owner | Course owner (training) |
| Who applies | A CanalBox internet subscriber, or an Irembo agent acting for them |
| Pattern | Identify the router → choose the package and duration → the price comes from CanalBox → pay → IremboGov sends the renewal to CanalBox → Approved ("Subscription Renewed") |
| Lessons | C1 (endpoints), C2 (fetch on the form), C3 (push in the workflow), B3 (Price From Attribute), B7 (actions) |
| Payment | RWF, valid 1 hour |
| SLA | 5 minutes |
| Version | V.2.0.0 (training). It replaces V.1.0.0 of 30 July 2024, which left the endpoints "to be confirmed". |
| Item | English | French | Kinyarwanda |
|---|---|---|---|
| Service name | [Your first name] - Renew CanalBox Internet Subscription | [Your first name] - Renouveler l'abonnement Internet CanalBox | [Your first name] - Kuvugurura ifatabuguzi rya interineti ya CanalBox |
| Summary | This service allows CanalBox internet subscribers to renew their subscription on IremboGov. You find your router by its serial number or by your phone number, keep your current package or choose a new one, choose the duration and pay. CanalBox renews your subscription right after payment. | Ce service permet aux abonnés Internet CanalBox de renouveler leur abonnement sur IremboGov. Vous retrouvez votre routeur par son numéro de série ou par votre numéro de téléphone, gardez votre offre actuelle ou en choisissez une nouvelle, choisissez la durée et payez. CanalBox renouvelle votre abonnement dès le paiement. | Iyi serivisi ifasha abafatabuguzi ba interineti ya CanalBox kuvugurura ifatabuguzi ryabo kuri IremboGov. Ushakisha router yawe ukoresheje nomero yayo yihariye cyangwa nomero ya telefoni yawe, ugakomeza ipaki ufite cyangwa ugahitamo indi, ugahitamo igihe kandi ukishyura. CanalBox ivugurura ifatabuguzi ryawe ako kanya umaze kwishyura. |
| Setting | Value |
|---|---|
| Category | Internet and Subscription Services |
| Who can apply | Individual: on. Business: off. |
| Languages | English, French, Kinyarwanda |
| Attachments | None |
| Certificate | None (invoice and receipt are produced by the payment platform) |
| Endpoint code | Used by | Payload keys sent | Answer used |
|---|---|---|---|
COURSE_CANALBOX_VERIFY_USER |
Field routerNumber |
routerNumber |
routerNumber, accountName, currentPackage (also subscriptionStatus, endDate, currency) |
COURSE_CANALBOX_ROUTERS_BY_PHONE |
Field phoneRouter |
phoneNumber |
routers[]: routerNumber, label, accountName, currentPackage |
COURSE_CANALBOX_OFFERS |
Field internetPackage |
routerNumber |
offers[]: name, label, pricePerMonth |
COURSE_CANALBOX_AMOUNT_PREVIEW |
Hidden fields previewSamePackage and previewNewPackage |
routerNumber, renewPreviousPackage, subscriptionDuration, and internetPackage when a new package is chosen |
totalPrice, currency, months, newPackage |
COURSE_CANALBOX_RENEWAL_PUSH |
Workflow, INTEGRATION on PAY, async: false |
The whole application. Its mapping reads applicationNumber, routerNumber or phoneRouter, renewPreviousPackage, internetPackage, subscriptionDuration, totalPrice |
Saved on the application: canalBoxTransactionId, subscriptionEndDate |
The push mapping looks for these exact field keys. A field called anything else sends nothing, and PAY fails with "routerNumber, transactionNumber, prepaidPeriod (1, 2, 3, 6 or 12) and amount are required."
Rules (wiki: Form configuration · Rules):
"required": false, "defaultRequired": true, plus the standard props.required expression.expressions.hide with the negated condition. hide clears the value. props.hideField: true keeps the value and is used for helper fields that fetches fill.YES, not Yes).| Section (key) | Block (key) | Visible when |
|---|---|---|
Router and package (routerSection) |
Router (routerBlock) |
always |
Package (packageBlock) |
selectedRouter has a value (see 3.3) |
| # | Block | Key | Label (EN) | Type | Req. | Validation and messages (EN) | Options (value: label) / fetch | Visible when |
|---|---|---|---|---|---|---|---|---|
| 1 | Router | identifyBy |
What do you wish to use? | radio | Yes | "This field is required." | ROUTER: Router serial number · PHONE: Phone number |
always |
| 2 | Router | routerNumber |
Router serial number | customgenericdatafetch | Yes | Pattern ^[A-Z0-9]{8}$: "The serial number has 8 capital letters or digits, e.g. CBXK0001." Fetch error: the partner's message (see 3.4) |
COURSE_CANALBOX_VERIFY_USER, triggerType TRIGGER_BUTTON, payloadKey routerNumber. Populates: accountName→accountName, currentPackage→currentPackage, routerNumber→selectedRouter |
identifyBy = ROUTER |
| 3 | Router | phoneNumber |
Phone number | input | Yes | Pattern ^07[2389][0-9]{7}$: "Enter a 10-digit Rwandan phone number, e.g. 0788100200." |
identifyBy = PHONE |
|
| 4 | Router | phoneRouter |
Router | customdropdowndatafetchpaginated | Yes | "Select a router." Empty list: "No router linked to this phone number is eligible. Please contact CanalBox." | COURSE_CANALBOX_ROUTERS_BY_PHONE, triggerType FIELD_LISTENER, payloadKey phoneNumber, dataset.dataField routers, bindLabel label, bindValue routerNumber. Populates: accountName→accountName, currentPackage→currentPackage, routerNumber→selectedRouter |
identifyBy = PHONE |
| 5 | Router | selectedRouter |
Selected router (helper) | input, props.hideField: true |
No | Filled by fields 2 and 4. It gives the package fetches one source that always exists. | never shown | |
| 6 | Router | accountName |
Names | input, read-only | No | Filled by the lookup | selectedRouter has a value |
|
| 7 | Package | renewPreviousPackage |
Renew previous subscription? | radio | Yes | "This field is required." | YES: Yes · NO: No |
always (inside the block) |
| 8 | Package | currentPackage |
Previous internet package | input, read-only | No | Filled by the lookup | renewPreviousPackage = YES |
|
| 9 | Package | internetPackage |
Internet package | customdropdowndatafetchpaginated | Yes | "This field is required." | COURSE_CANALBOX_OFFERS, FIELD_LISTENER, useMultiplePayloadKeys: true, payloadKeyMappings [{ "key": "routerNumber", "sourceField": "selectedRouter" }], dataField offers, bindLabel label, bindValue name |
renewPreviousPackage = NO |
| 10 | Package | subscriptionDuration |
Subscription duration (months) | customdropdown (static) | Yes | "This field is required." | 1, 2, 3, 6, 12 (labels "1 month", "2 months"...) |
renewPreviousPackage has a value |
| 11 | Package | previewSamePackage |
(hidden fetch) | customconditionaldatafetch, hideField: true |
No | COURSE_CANALBOX_AMOUNT_PREVIEW, FIELD_LISTENER, useMultiplePayloadKeys: true, mappings routerNumber←selectedRouter, renewPreviousPackage←renewPreviousPackage, subscriptionDuration←subscriptionDuration. Populates totalPrice→totalPrice |
renewPreviousPackage = YES |
|
| 12 | Package | previewNewPackage |
(hidden fetch) | customconditionaldatafetch, hideField: true |
No | As 11, plus internetPackage←internetPackage |
renewPreviousPackage = NO |
|
| 13 | Package | totalPrice |
Total price (RWF) | number, read-only | Yes | Min 20000, max 540000 | Filled by 11 or 12 | subscriptionDuration has a value |
Notes:
totalPrice sits in the same block as the fetches that fill it, so no cross-section setting is needed.label already includes it (for example "CanalBox 100 Mbps - 30,000 RWF per month").selectedRouter (FIELD_LISTENER caveat)A FIELD_LISTENER fetch with several payload keys fires only when every source control it found has a value. A control that does not exist when the fetch starts (because it is hidden with hide) is skipped, and the fetch does not notice if it appears later.
If internetPackage read routerNumber and phoneRouter directly:
The helper selectedRouter is filled by both lookups and kept by hideField, so the package fetches always read one existing control. The Package block appears only once a router is identified, so its fetches start after the method is chosen.
TC6 and TC7 check this behaviour.
| Situation | EN | FR | RW |
|---|---|---|---|
| Router not found (CBXK9999) | Error returned by the endpoint: "No CanalBox subscription matches this router or phone number." | (endpoint message, shown as returned) | (endpoint message, shown as returned) |
| Router being moved (CBXK0003) | Error returned by the endpoint: "This router is being moved to a new address. Renew after the move is complete." | (endpoint message, shown as returned) | (endpoint message, shown as returned) |
| Price unavailable | "We could not get the price from CanalBox. Please try again in a few minutes." | "Impossible d'obtenir le prix auprès de CanalBox. Réessayez dans quelques minutes." | "Ntitwabashije kubona igiciro kuri CanalBox. Ongera ugerageze mu minota mike." |
| Setting | Value |
|---|---|
| Type | Paid, dynamic, one scenario with no condition |
| Set price to | Price From Attribute, attribute totalPrice, currency RWF, minimum 20,000, maximum 540,000 |
| When the applicant pays | On submission (APPLY) |
| Payment expiration time | 1 hour |
| Merchant | GOR |
| Payment account | GOR-CG-RWF (fixed) |
| Service payment code | RRA-31e2dcebcd (fixed) |
The minimum and maximum come from the mock catalogue: 20,000 (50 Mbps, 1 month) to 540,000 (200 Mbps, 12 months). A totalPrice outside that range blocks the bill instead of charging a wrong amount.
| State code | State name EN | FR | RW |
|---|---|---|---|
NEW |
New | Nouveau | Gishya |
PAYMENT_PENDING |
Payment Pending | Paiement en attente | Gutegereza kwishyura |
PAYMENT_EXPIRED |
Payment Expired | Paiement expiré | Igihe cyo kwishyura cyarangiye |
APPROVED |
Subscription Renewed | Abonnement renouvelé | Ifatabuguzi ryavuguruwe |
| # | Start | Event | Who | End | Breaking action | Non-breaking |
|---|---|---|---|---|---|---|
| T1 | NEW | APPLY | ROLE_CITIZEN, ROLE_AGENT |
PAYMENT_PENDING | BILL_ID_GENERATION |
N1 |
| T2 | PAYMENT_PENDING | PAY | system authorised | APPROVED | INTEGRATION { "endpointCode": "COURSE_CANALBOX_RENEWAL_PUSH", "async": false } |
N2 |
| T3 | PAYMENT_PENDING | EXPIRE_PAYMENT | system authorised | PAYMENT_EXPIRED | N3 | |
| T4 | PAYMENT_EXPIRED | PAY | system authorised | APPROVED | same INTEGRATION as T2 | N2 |
Why the push is breaking:
PAYMENT_PENDING, and the failure is recorded by PROCESSING_FAILURE_TRACKER.Sync vs async:
PAID state. The source SRD's separate "Paid" notification is merged into N2.None. No office, no officer form, no correction loop. A paid application either renews automatically or stays in PAYMENT_PENDING for support.
Every placeholder carries !"". The router shown is ${routerNumber!""}${phoneRouter!""}. Only one of them has a value, because the hidden one is cleared.
| Lang | SMS | Email subject | Email body |
|---|---|---|---|
| EN | Dear ${applicantName!""}, your application for ${serviceName!""} was submitted. Bill number: ${billReferenceNumber!""}. Amount: ${price!""} ${currency!""}. Pay before ${paymentExpiration!""}. For support, call 9099. | Application submitted | Dear ${applicantName!""}, Your application for ${serviceName!""} was submitted. Router: {phoneRouter!""} Duration: ${subscriptionDuration!""} month(s) Bill number: ${billReferenceNumber!""} Amount due: ${price!""} ${currency!""} Pay before: ${paymentExpiration!""} Need help? Email support@irembo.com or call 9099. |
| FR | Cher(e) ${applicantName!""}, votre demande de ${serviceName!""} a été soumise. Facture : ${billReferenceNumber!""}. Montant : ${price!""} ${currency!""}. Payez avant le ${paymentExpiration!""}. Assistance : 9099. | Demande soumise | Cher(e) ${applicantName!""}, Votre demande de ${serviceName!""} a été soumise. Routeur : {phoneRouter!""} Durée : ${subscriptionDuration!""} mois Numéro de facture : ${billReferenceNumber!""} Montant à payer : ${price!""} ${currency!""} À payer avant le : ${paymentExpiration!""} Besoin d'aide ? Écrivez à support@irembo.com ou appelez le 9099. |
| RW | Kuri ${applicantName!""}, dosiye yanyu isaba ${serviceName!""} yoherejwe. Nomero yo kwishyuriraho: ${billReferenceNumber!""}. Amafaranga: ${price!""} ${currency!""}. Mwishyure mbere ya ${paymentExpiration!""}. Ubufasha: 9099. | Dosiye yoherejwe | Kuri ${applicantName!""}, Dosiye yanyu isaba ${serviceName!""} yoherejwe. Router: {phoneRouter!""} Igihe: amezi ${subscriptionDuration!""} Nomero yo kwishyuriraho: ${billReferenceNumber!""} Amafaranga yo kwishyura: ${price!""} ${currency!""} Mwishyure mbere ya: ${paymentExpiration!""} Mukeneye ubufasha, mwandikire support@irembo.com cyangwa muhamagare 9099. |
| Lang | SMS | Email subject | Email body |
|---|---|---|---|
| EN | Dear ${applicantName!""}, your CanalBox subscription for router {phoneRouter!""} is renewed until ${subscriptionEndDate!""}. Amount paid: ${price!""} ${currency!""}. Application: ${applicationNumber!""}. For internet issues, contact CanalBox; for payment issues, call 9099. | Internet subscription renewed | Dear ${applicantName!""}, We received your payment of ${price!""} ${currency!""} and CanalBox has renewed your internet subscription. Router: {phoneRouter!""} Valid until: ${subscriptionEndDate!""} CanalBox reference: ${canalBoxTransactionId!""} Application number: ${applicationNumber!""} For internet issues, contact CanalBox. For payment issues, email support@irembo.com or call 9099. |
| FR | Cher(e) ${applicantName!""}, votre abonnement CanalBox pour le routeur {phoneRouter!""} est renouvelé jusqu'au ${subscriptionEndDate!""}. Montant payé : ${price!""} ${currency!""}. Demande : ${applicationNumber!""}. Internet : contactez CanalBox ; paiement : 9099. | Abonnement Internet renouvelé | Cher(e) ${applicantName!""}, Nous avons reçu votre paiement de ${price!""} ${currency!""} et CanalBox a renouvelé votre abonnement Internet. Routeur : {phoneRouter!""} Valable jusqu'au : ${subscriptionEndDate!""} Référence CanalBox : ${canalBoxTransactionId!""} Numéro de demande : ${applicationNumber!""} Pour un problème de connexion, contactez CanalBox. Pour un problème de paiement, écrivez à support@irembo.com ou appelez le 9099. |
| RW | Kuri ${applicantName!""}, ifatabuguzi rya CanalBox rya router {phoneRouter!""} ryavuguruwe kugeza ${subscriptionEndDate!""}. Amafaranga mwishyuye: ${price!""} ${currency!""}. Dosiye: ${applicationNumber!""}. Ikibazo cya interineti: mwegere CanalBox; ikibazo cyo kwishyura: 9099. | Ifatabuguzi rya interineti ryavuguruwe | Kuri ${applicantName!""}, Twakiriye ubwishyu bwanyu bwa ${price!""} ${currency!""} kandi CanalBox yavuguruye ifatabuguzi ryanyu rya interineti. Router: {phoneRouter!""} Rizarangira: ${subscriptionEndDate!""} Nomero ya CanalBox: ${canalBoxTransactionId!""} Nomero ya dosiye: ${applicationNumber!""} Ku kibazo cya interineti, mwegere CanalBox. Ku kibazo cyo kwishyura, mwandikire support@irembo.com cyangwa muhamagare 9099. |
| Lang | SMS | Email subject | Email body |
|---|---|---|---|
| EN | Dear ${applicantName!""}, the bill ${billReferenceNumber!""} for ${serviceName!""} has expired. Please apply again to renew your subscription. For support, call 9099. | Payment expired | Dear ${applicantName!""}, The payment time for bill {serviceName!""}) has ended. Please submit a new application to renew your subscription at the current price. Need help? Call 9099. |
| FR | Cher(e) ${applicantName!""}, la facture ${billReferenceNumber!""} pour ${serviceName!""} a expiré. Faites une nouvelle demande pour renouveler votre abonnement. Assistance : 9099. | Paiement expiré | Cher(e) ${applicantName!""}, Le délai de paiement de la facture {serviceName!""}) est dépassé. Soumettez une nouvelle demande pour renouveler votre abonnement au prix actuel. Besoin d'aide ? Appelez le 9099. |
| RW | Kuri ${applicantName!""}, igihe cyo kwishyura ${billReferenceNumber!""} kuri ${serviceName!""} cyarangiye. Mwongere musabe kugira ngo muvugurure ifatabuguzi. Ubufasha: 9099. | Igihe cyo kwishyura cyarangiye | Kuri ${applicantName!""}, Igihe cyo kwishyura {serviceName!""}) cyarangiye. Mwongere musabe kugira ngo muvugurure ifatabuguzi ku giciro kiriho ubu. Mukeneye ubufasha, muhamagare 9099. |
Support routing:
| # | Title EN / FR / RW | EN | FR | RW |
|---|---|---|---|---|
| 1 | Payment / Paiement / Kwishyura | Use your bill number to pay within 1 hour with any method in the Payment options section. | Utilisez votre numéro de facture pour payer dans l'heure avec l'un des moyens de la section Options de paiement. | Koresha nomero yo kwishyuriraho wishyure mu isaha imwe ukoresheje bumwe mu buryo buri mu gice cy'Amahitamo yo kwishyura. |
| 2 | Renewal confirmation / Confirmation du renouvellement / Kwemeza ivugururwa | A few minutes after payment, an SMS and an email confirm that CanalBox has renewed your subscription and give its end date. | Quelques minutes après le paiement, un SMS et un e-mail confirment que CanalBox a renouvelé votre abonnement et indiquent sa date de fin. | Iminota mike nyuma yo kwishyura, ubutumwa bugufi na imeyili byemeza ko CanalBox yavuguruye ifatabuguzi ryawe kandi bikerekana igihe rizarangirira. |
| Key | English | French | Kinyarwanda |
|---|---|---|---|
| identifyBy | What do you wish to use? (Router serial number / Phone number) | Que souhaitez-vous utiliser ? (Numéro de série du routeur / Numéro de téléphone) | Ni iki wifuza gukoresha? (Nomero yihariye ya router / Nomero ya telefoni) |
| routerNumber | Router serial number · placeholder "Enter your router serial number" | Numéro de série du routeur · "Saisissez le numéro de série de votre routeur" | Nomero yihariye iranga router · "Andika nomero yihariye ya router yawe" |
| phoneNumber | Phone number · "Enter your phone number" | Numéro de téléphone · "Saisissez votre numéro de téléphone" | Nomero ya telefoni · "Andika nomero ya telefoni yawe" |
| phoneRouter | Router · "Select a router" | Routeur · "Sélectionnez un routeur" | Router · "Hitamo router" |
| accountName | Names | Noms | Amazina |
| renewPreviousPackage | Renew previous subscription? (Yes / No) | Renouveler l'abonnement précédent ? (Oui / Non) | Kuvugurura ifatabuguzi riheruka? (Yego / Oya) |
| currentPackage | Previous internet package | Offre Internet précédente | Ipaki ya interineti iheruka |
| internetPackage | Internet package · "Select an internet package" | Offre Internet · "Sélectionnez une offre Internet" | Ipaki ya interineti · "Hitamo ipaki ya interineti" |
| subscriptionDuration | Subscription duration (months) | Durée de l'abonnement (mois) | Igihe ifatabuguzi rizamara (amezi) |
| totalPrice | Total price (RWF) | Prix total (RWF) | Igiciro cyose (RWF) |
| Required message | This field is required. | Ce champ est obligatoire. | Iki gice kirasabwa. |
| Value | Behaviour |
|---|---|
| CBXK0001 | Active, CanalBox 50 Mbps. Same package: 20,000 RWF per month |
| CBXK0002 | Expired, CanalBox 100 Mbps. Same package: 30,000 RWF per month |
| CBXK0003 | Being moved: the lookup, the price preview and the push return the error "This router is being moved to a new address. Renew after the move is complete." |
| CBXK9999 (any other) | Not found: the lookup returns the error "No CanalBox subscription matches this router or phone number." |
| 0788100200 | Two routers: CBXK0001 and CBXK0002 |
| 0788100300 | Its only router is being moved: empty list |
| Packages | 50 Mbps 20,000 · 100 Mbps 30,000 · 200 Mbps 45,000 RWF per month |
| Durations | 1, 2, 3, 6, 12; any other value returns an error |
| Case | Steps | Expected |
|---|---|---|
| TC1 Router, same package | ROUTER, CBXK0001, fetch, YES, 3 months | Names filled; previous package "CanalBox 50 Mbps"; total 60,000 RWF; bill of 60,000 |
| TC2 Phone, new package | PHONE, 0788100200, choose CBXK0002, NO, 200 Mbps, 2 months | Two routers listed; total 90,000 RWF |
| TC3 Not found | ROUTER, CBXK9999 | The error "No CanalBox subscription matches this router or phone number." at the router lookup; nothing filled; Package block hidden |
| TC4 Being moved | ROUTER, CBXK0003 | The error "This router is being moved to a new address. Renew after the move is complete." at the router lookup, before any application exists (so there is no application number). Nothing is filled and the applicant cannot continue. Record what the applicant sees (C4 deliverable) |
| TC5 Empty list | PHONE, 0788100300 | Empty router list with the message in 3.2 |
| TC6 Switch method | ROUTER CBXK0001 → fetch → switch to PHONE 0788100200 → pick CBXK0002 → NO | The packages list loads for CBXK0002; selectedRouter = CBXK0002 |
| TC7 Switch renewal choice | TC1 up to the total (60,000) → switch to NO → pick 100 Mbps → back to YES | The total follows each change: 90,000 for NO with 100 Mbps; 60,000 again for YES. It never shows a total from the other choice. |
| TC8 Pay and renew | Submit TC1, pay on staging | APPROVED, state name "Subscription Renewed"; application details contain canalBoxTransactionId and subscriptionEndDate; N2 shows both |
| TC9 Push failure | Change the key routerNumber to ROUTER_SERIAL on a test copy, apply and pay |
PAY fails; the application stays in PAYMENT_PENDING; Kibana shows the push error. Restore the key afterwards |
| TC10 Languages | Switch to FR and RW | No English text or raw key left |
Deliverables (C4): the change request link; the application number of TC8 with its canalBoxTransactionId; TC4 with what the applicant saw; a screenshot of the Kibana push lines.
| V.1.0.0 | V.2.0.0 (this page) |
|---|---|
| Endpoints "to be confirmed"; API mapping table empty | Five named endpoints with payload keys and answers (section 2) |
| Router serial "13 or 8 characters" | 8 characters for the training mocks; production format still to be confirmed by CanalBox |
| No field keys | Keys fixed, because the push mapping reads them |
| Statuses Payment Pending → Paid → Approved, with a callback | Training uses a sync push PAY → APPROVED; the async design is described in 5.2 |
Variables $service_name, $billing_number, $amount, $router_number |
Real placeholders (${serviceName!""}, ${billReferenceNumber!""}, ${price!""}, ${routerNumber!""}) with full EN/FR/RW texts |
| No expiry handling | EXPIRE_PAYMENT and late payment transitions |
| Phone-number labels in the wrong language order | Fixed in section 9 |
| Product manager, go-live date "not yet set" | Owner: Course owner (training) |