Zayid iOS ↔ Website Parity QC Board

Test cases for iOS EndUser gaps vs trusted Website + Backend. Compare Arabic UI labels on both clients. Mark each row when done — progress is saved in this browser.

170 scenarios P0 5 · P1 40 · P2 89 · P3 36 Source: parity review

What this covers

Trusted sources: Website EndUser + Backend APIs. Under test: iOS EndUser app (SwiftUI shell + legacy UIKit where still used). Kingdom catalog is not live bidding — keep Auction vs Kingdom separate.
How to useWork module by module from the sidebar. Tick the checkbox when the scenario passes. Click the eye icon for full steps, pass/fail criteria, and evidence paths.
Arabic UISteps include Arabic labels from the product (e.g. المحفظة, المزايدة). Use those names when navigating.
Issue codesPrimary gap ID is shown in the ID column. Extra related codes appear under it. Use them in defect reports.
Website-only skipsW4-NOTIF-006, W4-NOTIF-007, W3-DTO-010, W3-DTO-011, W3-DTO-006, W6-DET-001, W6-DET-002
Review notes
  • W9 exceptional bidders (W9-EXC-*): Agent Portal only; EndUser fee waiver is server-side. Website and iOS both have no exceptional UI — no iOS QC gap.
  • W7-AWD-006: RevokeProperty emits Wallet but not property status — shared backend limitation; both clients affected. Bid screen mitigates with refetch. Tracked as informational P3 scenario.

Before you start

ItemAction
EnvironmentStaging (or agreed build) with matching Website + API + iOS build from the parity review.
AccountsSame EndUser account on Website and iOS when comparing money, bids, wallet, and notifications.
ReferenceWhen iOS and Website disagree, Website + Backend win unless the review note says both are wrong.
LanguageTest iOS in Arabic UI. Match Arabic paths in the detail modal.
ProgressCheckmarks persist in localStorage on this machine/browser only.

Priority & tags

Priority: click to include (any selected priority matches).
Tags: click cycles must havemust not have → off. Example: P1 + timer must have + text must not have = all P1 with timer but not text. All must have tags are required together (AND).

Eye icon = test steps

Tags

Live Bidding · المزايدة (31)

IDTagsPriScenario — what happens / what’s wrongShould be (correct)
W3-DTO-002
W3-DET-002
bidding dto P0
Specialty lots (camel/vehicle/etc.) crash or blank property detail
تفاصيل المزايدة، إبل، مركبات
Live auctions sell camels, falcons, vehicles, and other non–real-estate lots. Those lots must open and allow bidding like real-estate lots.
What’s wrong: Opening a camel/vehicle/falcon lot shows a blank screen, error, or missing bid chrome (no timer, no confirm).
Detail loads with specialty specs and full bid UI, matching Website for the same lot.
W1-BID-001
W1-BID-002
signalr bidding P1
BidsNumber not reset after success or Property SignalR updates
تأكيد المزايدة، عدد المزايدات
Backend uses client bid-count increment rules. Stale local CountsNumber can send wrong increments and confuse successive bids.
What’s wrong: After a successful bid or after agent updates the lot, the next bid may use a stale increment count.
Reset local bid count after successful bid and when applying SignalR Property updates (mirror Website).
W1-BID-003
bidding P1
Confirm blocked when maxBid is nil on opening-price lot
تأكيد المزايدة، سعر الافتتاح
First bid on a lot with no bids uses opening price; Website/Backend allow MaxBid ?? OpeningPrice.
What’s wrong: Confirm is disabled or blocked on a lot with zero bids even when opening price is valid.
User can confirm first bid at opening price path like Website.
W1-CALC-001
calculations bidding wallet P1
Hardcoded 15% striving VAT instead of API tax rate
قيمة السعي، الضريبة
Tax percentage on striving fees comes from configuration. Wrong % shows wrong total to the bidder.
What’s wrong: Fee/tax lines always use 15% even when auction config differs.
Use API strivingPriceTexes; totals match Website for same lot.
W1-CALC-002
calculations bidding P1
Opening vs current price gated on empty bidders page
سعر الافتتاح، أعلى مزايدة
Banner and fees should use bidNumber/maxBid from property details, not whether the paginated bidders list is still empty.
What’s wrong: Lot shows opening-price framing even when bids exist (or opposite), until bidders list loads.
Gate on API bid count fields like Website, independent of bidders page load.
W9-BOARD-003
W9-BOARD-002
W3-DTO-008
W9-BOARD-001
signalr bidding dto P1
Own-bid detection uses phone; missing applicationUserId on board
لوحة المزايدين، مزايدتي
After your bid arrives live, the app must recognize it as yours for flags like "you have bid on this lot".
What’s wrong: Your live bid is not marked as yours; "isUserHasAnyBid" / own-row highlight may stay wrong because phone is never in SignalR payload.
Match applicationUserId; own rows/highlight work like Website.
W2-FEE-003
no-website calculations signalr P2
Bid screen wallet snapshot is stale on open — no API refetch on appear
تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح، المحفظة
Before bidding, the app should reflect the latest available balance after deposits, holds, or releases — especially after returning from SADAD/bank app.
What’s wrong: BidOnItemPresenter.init sets currentWalletData from UserDefaultsManager.getWalletData() once. No getWallet() on viewDidLoad/appear. Commented-out client pre-check (~L670–679) would use this stale snapshot. SignalR Wallet listener updates cache only when event fires.
Website does not show wallet on bid screen and relies on backend 73 at submit — acceptable. iOS does load wallet into presenter state for validation scaffolding; that state should be fresh. Wallet screen refetches on UIApplication.didBecomeActiveNotification (ZYID-2458 pattern); bid screen does not.
W5-ONSITE-012
bidding onsite P2
BidderRepresentativeList omits propertyIds array
تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح، نوع الممثل
Representative row can scope to specific interested lots for agent paddle assignment.
What’s wrong: Interactor never sends BidderRepresentativeList[0].propertyIds; Website form defines propertyIds: [[]] but also often leaves it empty at submit.
When interests selected, representative row should include same property GUIDs for downstream AddOnsiteBidder PropertyIds when agent portal expects scoping.
W5-REP-001
bidding dto P2
BidOnItemHelpers swaps Pending and Approved in representationStatusEnum
تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح، نوع الممثل
A bidder whose agency request is still under review must not be treated as approved (or vice versa) for any bid-eligibility helper.
What’s wrong: PropertyDetailsResult.representationStatusEnum maps bidderRepresentitveStatus 1→approved, 2→pending (inverted).
Backend + Website: Pending=1, Approved=2, Rejected=3 (BidderOrganizationRepresentitveEnum, GetPropertyDetailsOutputDTO.ts). BidOnItemPresenter already uses the correct mapping.
W1-BID-007
calculations bidding P2
iOS does not reject zero or negative bid amounts before submit
تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح
Bidders must not send non-positive amounts; the client should block early with the same message as Website.
What’s wrong: confirmBid / addNewBid never checks currentLocalBidding > 0.
Website addNewBid() returns early when userAmount <= 0 with “لا يمكن المزايدة بصفر أو أقل!!”.
W5-HYB-002
text timer bidding P2
iOS missing Arabic message for onsite-only bidder (TransactionNotAccept)
تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح، جاري
A user registered as an onsite (hall) bidder must not place bids through the online channel; the product should explain that clearly.
What’s wrong: AddNewBidModel.userMessage(forStatusCode:) has no case for 76 (ResponseStatusCode.TransactionNotAccept). Onsite users get generic “قم بالمزايدة بمبلغ اخر” instead of the website toast.
Website shows المستخدم حضوري ولا يمكن المزايدة من الموقع when statusCode === TransactionNotAccept (real-estate-details.component.ts ~782–784). Backend returns this when an onsite-linked user attempts online AddNewBid.
W7-ACT-006
bidding dto P2
iOS My Bids cards hide bids count badge
تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح، مزايداتي
Bid count on card signals auction heat at a glance.
What’s wrong: MyBidsSUIItem decodes bidsCount but MyBidsItemCardView never renders it.
Website overlay shows {{Item.bidsCount}} مزايدة on card image.
W7-ACT-005
calculations bidding dto P2
iOS My Bids cards omit per-meter bid breakdown
For biddingTypeId == 2 (per sqm), user compares their bid and highest bid per meter.
What’s wrong: MyBidsSUIItem has no propertyDataDTO; card shows raw amount / highestBid strings only.
Website my-bids-card when propertyDataDTO.biddingTypeId == 2 shows قيمة مزايدتك للمتر, اعلى مزايدة للمتر, and المساحة بالمتر (amount/areaNumerical, highestBid/areaNumerical).
W7-ACT-007
bidding P2
iOS My Bids uses page size 5 and infinite scroll only
تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح، مزايداتي
User controls how many bids appear per page and jumps pages on long histories.
What’s wrong: MyBidsSUIPresenter.pageSize = 5; infinite scroll appends pages; no page-size picker or page jumper.
Website app-PaginationControls exposes page size and page number; default pagination from shared Pagination model (typically 10).
W8-UX-016
text bidding P2
iOS my-bids search field has empty placeholder
تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح، البحث
Users search auctions by name on my-bids list
What’s wrong: TextField("", text: $presenter.searchText) — no placeholder (MyBidsSUIView.swift)
Website placeholder البحث باسم المزاد (my-auctions.component.html:19)
W1-BID-006
text bidding P2
iOS omits two Website AddNewBid error codes in user messaging
تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح
Bidders need the same Arabic explanations for onsite-only accounts and expired representation requests.
What’s wrong: AddNewBidModel.userMessage maps 82, 73, 86, 3, 2, 88, 85, 83, 4, 8 but not 76 (TransactionNotAccept) or 104 (CanNotBidWithExpiredRepresentationRequest).
Website shows “المستخدم حضوري ولا يمكن المزايدة من الموقع” (76) and “لا يمكن المزايده بطلب تمثيل غير صالح اعد تحميل الصفحة” (104).
W8-TERM-007
no-website text calculations P2
iOS shows bid success alerts Website does not show
تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح
Post-bid feedback should match Website: silent success with live UI refresh; errors only via toast/alert.
What’s wrong: SwiftUI: BidOnItemPresenter.addNewBid → showSuccessAlert(message: "تم إضافة المزايدة بنجاح"). UIKit: BiddingVC → "تمت المزايده بنجاح". BidOnItemView binds .alert(... success ...).
Website real-estate-details.component.ts: on successful bid, updates state/refetch — no success toast (errors use toastr.ErrorWithTroubleshooting).
W1-CALC-003
text calculations bidding P2
iOS skips Website’s 3-decimal intermediate rounding on fee lines
تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح، المحفظة
Fee breakdown lines (striving, VAT on striving, property tax, total) should match Website figures the bidder uses to decide whether to bid.
What’s wrong: calculateFeesAndTaxes keeps full Decimal precision; formatNumber renders 2 decimal places. No toFixed(3) per component.
Website UpdateViewValues rounds each of taxesValue, strivingPriceValue, strivingPriceTaxesValue, and totalAmount with parseFloat(...toFixed(3)). Backend awarding math uses Math.Round(..., 3) on components.
W1-BID-004
bidding P2
Legacy UIKit BiddingVC references deleted BiddingPresenter
تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح
Secondary UIKit bidding screen should share the same bid actions as Website/SwiftUI or be removed from the target.
What’s wrong: BiddingVC.swift declares var presenter: BiddingPresenter? and BiddingPresenter(biddingView:propertyId:) but BiddingPresenter.swift is absent from the repo; file not listed in project.pbxproj.
Either wire BiddingVC to BidOnItemPresenter (which already receives increaseBid/confirmBid calls per codegraph callers) or delete unreachable UIKit bidding.
W5-ONSITE-011
bidding onsite P2
Registered bidder can still open full registration sheet
تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح، التسجيل الحضوري
After successful onsite registration, user should see confirmation only — not re-enter the 3-step form.
What’s wrong: When isExistingBidder, UI shows green confirmation card (good), but comment in shouldShowOnsiteButton says user can “always re-open the form”; registered state is non-tappable (aligned). Legacy path unclear for re-registration attempts.
Website hides register button when isExistingBidder; shows attended-bidder confirmation section only.
W7-ACT-008
bidding P2
Search debounce semantics differ on My Bids
تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح، البحث
Search by auction name should not spam API on partial typing.
What’s wrong: MyBidsSUIPresenter debounces 500ms and refetches on any searchText change (including 1–2 characters).
Website searchForm debounces 300ms with filter(v => v == null
W8-TERM-004
text calculations bidding P2
SwiftUI bids header uses highest_bid (اعلى مزايدة) instead of Website bid-value labels
Bids tab summary row should describe the current leading bid amount using the same words as Website.
What’s wrong: BidsListView labels non-meter column with BidOnItemLocalizedKeys.highestBid → AR اعلى مزايدة (missing hamza on أ).
Website: قيمة المزايدة (sidebar + bidder list); meter variant قيمة المزايدة للمتر.
W8-TERM-003
text bidding P2
UIKit bid screen shows أعلي مزايدة (typo + wrong term) when bids exist
After first bid, users should see current bid semantics (قيمة المزايدة / السعر الحالي) — not “highest bid” marketing language.
What’s wrong: BiddingVC.setTexts sets highestBidTitleLabel.text = "أعلي مزايدة"; table cells use أعلي مزايدة (لكل متر); storyboard fragment matches.
Website item sidebar: قيمة المزايدة (item-detailed-card.component.html); cards use السعر الحالي when maxBid set (favorite-card, property-card). Website bidder list column: قيمة المزايدة.
W8-UX-015
text bidding P3
Empty my-bids button shorter than Website
تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح
Consistent re-engagement CTA on zero-bid state
What’s wrong: Hardcoded button تصفح المزادات in MyBidsSUIView
Website: تصفح المزادات الآن (my-auctions.component.html:71)
W7-AWD-006
no-website bidding wallet P3
Informational: RevokeProperty emits Wallet only (shared backend)
المحفظة
When an award is revoked, backend emits Wallet but not property status. Both Website and iOS are affected; iOS bid screen may mitigate with refetch.
What’s wrong: Property award status may stay stale until manual refresh after revoke; wallet updates.
Known shared limitation — document; prefer refetch property after Wallet if needed.
W2-FEE-006
no-website calculations bidding P3
iOS bid client-side entry-fee balance pre-check is commented out (Website also relies on backend 73)
تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح، المحفظة
Optional early warning before submit: "wallet does not cover entry fee" — reduces failed bid attempts.
What’s wrong: BidOnItemPresenter.confirmBid has UIKit-era wallet/entry-fee gate commented out (~L670–679). User proceeds to confirmation and learns only from API 73.
Website real-estate-details.component.ts has no client pre-check — only maps 73 after addNewBid. Backend gate is authoritative.
W1-BID-008
text bidding P3
iOS success toast copy differs from Website silent success
تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح
Minor UX consistency after a winning bid submission.
What’s wrong: Shows “تم إضافة المزايدة بنجاح” alert; Website only updates state (no success toast on 200). Legacy UIKit used “تمت المزايده بنجاح”.
Product choice: either align to Website (state-only) or standardize one Arabic success string app-wide.
W7-ACT-011
bidding dto P3
isLastBid decoded but not shown on iOS My Bids
تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح، مزايداتي
User sees whether they are currently the highest bidder on that lot.
What’s wrong: MyBidsSUIItem.isLastBid populated from API; card UI ignores it.
Website DTO includes isLastBid; UI may surface winning state (verify product intent on Website template — field present in contract).
W8-TERM-010
text bidding P3
My Bids card hardcodes non-Website اعلى مزايدة
My Bids list should use same bid-value terminology as property/bid detail surfaces.
What’s wrong: MyBidsItemCardView label: "اعلى مزايدة" (hardcoded, missing hamza).
Website equivalent lists use قيمة المزايدة or السعر الحالي depending on context — not أعلى مزايدة.
W7-ACT-012
bidding dto P3
Selling agent name not shown on iOS My Bids cards
تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح، مزايداتي
Agent identity helps user distinguish lots across selling agents.
What’s wrong: agentName decoded on MyBidsSUIItem but not rendered (Website card also omits agent in current template — backend field exists).
Contract includes agentName; display is product-dependent.
W5-REP-005
bidding P3
SwiftUI primary bid area does not mirror Website “pending review” banner placement
تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح، نوع الممثل
While representation is pending, the bidder should see a clear waiting state and must not think they can bid yet.
What’s wrong: Pending state is visible on the Representation tab (PendingRepresentationView) but the main bid footer relies on disabled/hidden controls without the prominent waiting banner Website shows next to bid CTAs.
Website shows طلب التمثيل قيد الإنتظار waiting div beside bid controls when isBidderRepresentativePending() (real-estate-details.component.html ~501–520). Bid confirm hidden unless approved.

SignalR / Live Updates · التحديثات المباشرة (10)

IDTagsPriScenario — what happens / what’s wrongShould be (correct)
W1-HUB-001
W9-HP-001
timer signalr bidding P1
Bid screen never joins Auction group — parent auction updates missed
جاري، إنتهى المزاد، تفاصيل المزايدة
When the agent extends or changes the parent auction, bidders watching a lot must see updated end time/status without manual refresh. Critical for Hybrid Plus parent evening cap.
What’s wrong: While on lot detail, parent end-date extend or auction data change does not update status/counter until leave/re-enter.
Bid screen joins Auction_{id}; parent extend/AuctionData updates live like Website.
W9-BOARD-004
text signalr bidding P2
Attended (onsite) bidders not labeled as paddle numbers on SwiftUI board
التحديثات المباشرة، تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح
Onsite participants are identified by paddle number in the public board, not personal names
What’s wrong: BidRowView renders userName only; no check for isOnsiteBidder
Website: <span ngIf="item?.isOnsiteBidder"> مضرب رقم</span> before name; UIKit: "مضرب رقم \(userName)"
W1-HUB-004
signalr wallet P2
AuctionPublishDate group join is Home-tab scoped on iOS vs connection-level on Website
التحديثات المباشرة
When operations publishes a new live auction, home/auction lists should update without manual refresh
What’s wrong: HomeSUIPresenter.joinPublishDateGroup() runs on Home appear/connect only. User on Wallet/Profile/Kingdom/Auction-detail never joins until they revisit Home
Website JoinAuctionPublishDateGroup() runs inside startConnection() for every hub session
W1-BID-005
no-website calculations signalr P2
heightsOnlineBid not updated on live PropertyBid SignalR events
التحديثات المباشرة، تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح
iOS uses heightsOnlineBid in pre-submit stale checks; it must track the live highest bid like maxBid.
What’s wrong: updatePropertyBid handler updates maxBid and currentLocalBidding but not heightsOnlineBid.
Website does not use a separate stale flag; it resets amount from SignalR. iOS should keep heightsOnlineBid in sync with maxBid on every PropertyBid (as HTTP fetch already does ~442–445).
W7-ACT-013
signalr bidding P2
Legacy UIKit MyBids row tap opens auction hub, not bid screen
التحديثات المباشرة، تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح
Tapping a bid row should open the lot bidding/detail experience.
What’s wrong: MyBidsVC+Extensions pushes AuctionVC.buildVC(aucID:aucName:); commented line shows old AucDetailsVC path.
Primary SwiftUI path navigates to BidOnItemView(propertyId:); Website links to /item-details/:propertyId.
W8-TERM-008
text signalr bidding P2
UIKit wallet storyboard says المبلغ المحجوز instead of Website الرصيد المحجوز
Blocked wallet funds are balance (رصيد) reserved for bids — same term as Website wallet page.
What’s wrong: WalletStoryboard.storyboard label text المبلغ المحجوز.
Website wallet.component.html: الرصيد المحجوز (~L356).
W1-HUB-003
signalr P2
User-scoped representative groups are screen-level on iOS, connection-level on Website
التحديثات المباشرة، نوع الممثل، ممثل لنفسه، ممثل لشخص
When agent approves/rejects a bidder representative, the user should learn immediately regardless of which tab they are on
What’s wrong: propertyForUser_{userId} and auctionForUser_{userId} joins occur only inside AuctionSUIPresenter and BidOnItemSignalRManager while those screens are active. connectionDidOpen does not join them
Website calls PropertyForUserUpdate() and AuctionForUserUpdate() on every hub connect and again after login/register
W1-HUB-005
signalr wallet dto P3
iOS hub invoke names mix PascalCase and camelCase
التحديثات المباشرة
Stable wire names reduce cross-platform drift and ease debugging
What’s wrong: Same codebase uses AddToAuctionUpdatesGroup (Pascal) alongside addToPropertyUpdatesGroup, addToWalletUpdatesGroup, removeFromPropertyUpdatesGroup (camel)
Website and backend consistently use PascalCase hub method names matching PropertyHub.cs
W9-BOARD-005
signalr bidding P3
iOS prepends SignalR bids without popping excess rows
التحديثات المباشرة، تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح
Board shows a bounded recent-history window consistent across clients
What’s wrong: items.insert(newBidder, at: 0) with no length cap
Website on page 1: unshift + pop() when items.length > pageSize
W9-BOARD-006
signalr bidding privacy P3
UIKit highlights own row by bidder code match, not auth user id
التحديثات المباشرة، تأكيد المزايدة، أعلى مزايدة، سعر الافتتاح
Own-row highlight should be stable for the logged-in account
What’s wrong: BidderPersonCell.setasCurrentuser when row bidderCode == profile.bidderCode
Website uses applicationUserId == NameIdentifier (works even when name is masked empty)

Timers & Hybrid Plus · العدّاد والمزاد الهجين بلس (5)

IDTagsPriScenario — what happens / what’s wrongShould be (correct)
W7-ACT-010
timer dto hybrid-plus P2
GetMyAuctions DTO lacks timer/status fields needed for canonical Hybrid Plus cards
جاري، قادم، إنتهى المزاد، هجين بلس
Hybrid Plus lots need timeType, isExpire, phi/t (on bids list) for accurate live/coming/closed and extension display.
What’s wrong: MyBidsSUIItem uses legacy HP tri-state (isClosed + dates + parentAuctionEndDate) with code comments citing missing DTO fields; same gap on Website my-bids-card.
Counter-spec Q3: extend MyAuctionPropertiesDto (and interests DTO) with timeType, isExpire, waitingAwardingCommittee, visible; inject Phi/T on GetMyAuctions like interests service already does.
W8-STAT-009
text timer hybrid-plus P3
Hybrid Plus running row hardcodes Arabic جاري instead of localization key
جاري
Same canonical label, but EN parity requires keyed string
What’s wrong: MyInterestsItemCardView.hybridPlusRunningLabel uses Text("جاري")
Sibling views use auction_status_live.localized(); Website uses جاري in counters
W9-HP-005
text timer hybrid-plus P3
Missing timeType on HP Infinite open shows numeric counter instead of running message
جاري
Infinite open floor (isClosed=false, timeType=1) must never show a public hammer countdown — only جاري + running copy (Beat B).
What’s wrong: AuctionPropertyCardView.isHybridPlusRunning requires (item.timeType ?? 0) != 0. If timeType is nil (partial HP payload, race before refetch), card falls through to countdownDisplay targeting auctionEndDate.
Website showRunningMessage requires isClosed === false && timeType === 1 — strict equality, so nil does not show running message but also showCounter may still be true; iOS should not show misleading countdown when auctionTypeID==4 && isClosed==false and not in phi.
W9-TYPE-004
timer hybrid-plus P3
Non-HP detail — Website isAuctionFinished() uses backend propertyStatus hint; iOS uses getItemStatusEnum
جاري، قادم، إنتهى المزاد، هجين بلس
Finished vs active sections on detail should follow the same canonical rules as counters and bid gates. Backend propertyStatus is a hint (handbook §Four-way divergence); client canonical function is authoritative.
What’s wrong: iOS behavior diverges from Website for this case (W9-TYPE-004).
Both should derive finished state from canonical status (item dates for 1/2/3). iOS already does; Website detail has a legacy hint path.
W1-TIME-F003
timer hybrid-plus P3
PropertyCountdownTimerView uses legacy date logic, not wired in production
جاري، قادم، إنتهى المزاد، هجين بلس
Countdown/status on bid screens must follow one canonical rule (getItemStatusEnum) so timer and bid gate never disagree.
What’s wrong: PropertyCountdownTimerView.updateAuctionStatus() uses simplified date/isClosed checks and does not implement HP timeType, parent cap, or phi window. File is preview-only — production uses BidOnItemTimerManager + getItemStatusEnum.
Production path already uses BidOnItemTimerManager.getAuctionStatus() → getItemStatusEnum.

Wallet · المحفظة (12)

IDTagsPriScenario — what happens / what’s wrongShould be (correct)
W3-DTO-001
W2-API-002
calculations wallet dto P0
Wallet history truncates fractional SAR amounts
المحفظة، سجل العمليات، المبلغ
Users must see the exact amount deposited or withdrawn. Fractional riyals (halalah) are real money and must not be rounded or cut.
What’s wrong: A transaction of 1,234.56 SAR appears as 1,234 (or the row fails to load). Blocked transactions may show decimals correctly while regular ones do not.
Wallet history shows full precision matching Website and backend decimal amounts (e.g. 1,234.56).
W3-DTO-009
W2-API-001
wallet dto P1
Wallet transactions drop auction item id/name
المحفظة، سجل العمليات
Users should see which lot a wallet transaction relates to when backend provides auctionItemId/name.
What’s wrong: Regular transactions lack lot name/link that Website shows.
auctionItemId/name present and shown like Website (blocked txs already have linkage).
W2-FEE-001
text calculations wallet P2
iOS add-funds API path does not surface GoPay-disabled (status 90) with Website copy
المحفظة، الرصيد المتاح، الرصيد المحجوز
When electronic payment is turned off, the bidder should see that wallet top-up is unavailable and be directed to agent/check alternatives — not a generic failure.
What’s wrong: WalletInteractor.addFundsToWallet treats any non-success status (except 401) as generic "please_check_your_internet_connection_and_try_again". Status 90 (GoPayIsDisabled) is not distinguished.
Website wallet.component.ts shows: "الدفع الإلكتروني غير متاح حالياً .. من فضلك تواصل مع وكيل البيع للدفع عن طريق الشيكات" on status 90. Backend returns ResponseStatusCode.GoPayIsDisabled from WalletService.AddFundsToWallet when IsGoPayEnabled config is false.
W2-FEE-002
calculations wallet dto P2
iOS add-funds max amount uses hardcoded 10M instead of server MaxInvoiceLimit
المحفظة، الرصيد المتاح، الرصيد المحجوز
Each deposit invoice must respect the configured Sadad/GoPay ceiling; exceeding it should be blocked before API call with the same limit Website shows.
What’s wrong: AddToWalletView.validateAmount caps at 10,000,000 hardcoded. WalletSUIPresenter fetches maxInvoiceLimit from payment config but AddToWalletView does not consume it.
Website reads MaxInvoiceLimit from GetPaymentConfigurations, validates on input change, and shows formatted limit in error text. Backend rejects amounts above config in AddFundsToWallet.
W2-FEE-004
text calculations wallet P2
iOS withdraw does not map server InvalidData to Website Arabic over-balance message
المحفظة، الرصيد المتاح، الرصيد المحجوز
When refund request exceeds available balance (not total), user should see the same rejection copy Website shows.
What’s wrong: WalletInteractor.withDrawFromWallet maps non-success to generic errors. WalletSUIPresenter.withDrawFromWallet shows fixed "خطأ في عملية الاسترداد". WithdrawView has client-side amount > available check, but server rejection path is not mapped.
Website shows "المبلغ المطلوب إستردادة أكبر من المبلغ المتاح" on StatusCodeEnum.InvalidData (8). Backend WithdrawFundsFromWallet returns InvalidData when amount exceeds available.
W2-API-004
wallet dto P2
No server-side statusId filter on wallet transactions
Website lets users filter history by status (pending payment, paid, rejected, refunded, etc.) via API.
What’s wrong: Request omits statusId; WalletSUIPresenter / WalletPresenter filter client-side after full page fetch.
Website sends statusId in GetUserTransactionsWalletInputDto when user picks filter.
W8-TERM-006
text calculations wallet P2
Striving fee label uses رسوم السعي where Website uses قيمة السعي
Brokerage (striving) fee row must use قيمة not رسوم to match Website financial disclosure.
What’s wrong: striving_fee localized string = رسوم السعي (%@%%) used in DetailsTabContent / cost sheet via BidOnItemLocalizedKeys.strivingFee.
Website real-estate-details.component.html: قيمة السعي (~L144).
W2-API-003
wallet dto P2
Transaction list sends sortingTypes: 0 (None) instead of Website Descending
المحفظة، الرصيد المتاح، الرصيد المحجوز
Users expect newest transactions first (default sort by date descending).
What’s wrong: GetwalletTransactions hardcodes "sortingTypes": 0.
Website wallet-transactions.component uses SortingType.Descending (2); backend DTO default ctor also Descending.
W2-FEE-005
calculations wallet P3
Blocked-balance detail rows on iOS are not navigable to property details
المحفظة، الرصيد المتاح، الرصيد المحجوز، تفاصيل العقار
User reviewing held entry fees should jump to the lot they are winning — same as Website wallet blocked table.
What’s wrong: BlockedBalanceSheet / BlockedTransactionRow display name + amount only; no tap → property detail.
Website wallet.component.html links each blocked row to ['/item-details', item.auctionItemId].
W2-API-007
wallet dto P3
GetWallet stamp format differs (epoch ms vs ISO datetime)
المحفظة، الرصيد المتاح، الرصيد المحجوز
Anti-cache stamp on wallet POST body.
What’s wrong: iOS sends yyyy-MM-dd'T'HH:mm:ss; Website sends Date.getTime() string.
Either format acceptable — WalletService.GetWallet() does not read GetUserWalletInputDto.
W2-API-006
calculations signalr wallet P3
UIKit wallet path has no blocked-transactions API usage
المحفظة، الرصيد المتاح، الرصيد المحجوز
Blocked entry fees per active bid should appear in wallet blocked section.
What’s wrong: WalletPresenter / HomeWalletVC never call getBlockedWalletTransactions; feature exists only in SwiftUI WalletSUIPresenter.
Website wallet.component + wallet-transactions refresh blocked list on load and on Wallet SignalR event.
W2-API-005
wallet dto P3
Withdraw response decoded as add-funds model type
المحفظة، الرصيد المتاح، الرصيد المحجوز
Withdraw returns empty WithdrawFundsFromWalletOutputDto; success is status-only.
What’s wrong: withDrawFromWallet decodes body as AddFundToWalletResponseModel.
Use withdraw-specific wrapper (or generic ResponseResultDto with empty result).

Auth & Session · تسجيل الدخول (17)

IDTagsPriScenario — what happens / what’s wrongShould be (correct)
W4-AUTH-F002
auth P1
Account lockout (status 69) not shown on login
تسجيل الدخول، الحساب مقفل
Locked accounts must show a clear lockout message, not a generic OTP/login error.
What’s wrong: Locked user gets wrong/generic error when requesting OTP/login.
Status 69 maps to Website-equivalent lockout message.
W4-AUTH-F001
signalr wallet auth P1
Incomplete logout on Home / Wallet / Notifications paths
تسجيل الخروج
Logout must kill FCM device, clear wallet cache, ForceLogout, and reset SignalR so the next user does not inherit realtime groups.
What’s wrong: Logging out from some entry points leaves session/realtime state; next login may see prior user's live groups or wallet cache.
All logout entry points fully tear down like Profile → logout path.
W4-AUTH-F003
auth P1
Nafath-incomplete legacy users (status 65) blocked wrongly
نفاذ، تسجيل الدخول
Legacy users who still need Nafath completion must be guided through Nafath, not told they entered a wrong OTP.
What’s wrong: Status-65 users cannot proceed; see wrong-OTP style errors.
Detect 65 and route to Nafath completion like Website.
W8-UX-004
text auth P1
Registration SwiftUI flow Arabic-hardcoded (no EN parity)
إنشاء حساب، تسجيل جديد
English users must see localized signup, not Arabic-only hardcoded strings.
What’s wrong: Device/app in English still shows Arabic-only registration copy.
Localized signup stack matching Website EN/AR.
W8-UX-003
text auth P2
English OTP screen title contains typo “phonn” and vague wording
تسجيل الدخول، إنشاء حساب، تسجيل الخروج
OTP step must clearly state code was sent to mobile
What’s wrong: enter_otp_title EN = Enter the OTP sent to phonn number
Website AR: يُرجى إدخال الرمز المرسل على رقم الجوال …; EN legacy key: Enter otp received via sms on number
W8-UX-006
text auth P2
Forgot-password intro asks for “following data to create password” instead of ID + mobile
تسجيل الدخول، إنشاء حساب، تسجيل الخروج
User must enter national ID and registered mobile to receive reset OTP
What’s wrong: forgot_password_subtitle AR ادخل البيانات التالية لإنشاء كلمة مرور جديدة
Website step 1: قم بإدخال رقم الهوية و رقم الجوال (forget-password.component.html:52-53)
W8-UX-008
text auth P2
Legacy OTP screen always shows “رمز التحقق خاطئ” on failure
منتهي
OTP errors should distinguish invalid vs expired where applicable
What’s wrong: OTPVC.FailureAlert uses hardcoded رمز التحقق خاطئ regardless of server/presenter message
Website: invalid otp → AR رمز غير صحيح او منتهي; SwiftUI path uses otp_incorrect_error / otp_expired_error
W8-UX-001
text auth P2
Login screen subtitle uses generic “enter the following data” instead of ID + password instruction
تسجيل الدخول، إنشاء حساب، تسجيل الخروج
User must know exactly which credentials to enter before OTP is sent
What’s wrong: AR hardcoded: ادخل البيانات التالية لتسجيل الدخول in LoginView.swift
Website: قم بإدخال رقم الهوية و كلمة المرور لتسجيل الدخول (login.component.html)
W4-AUTH-F006
auth P2
Login/register OTP rate-limit and duplicate-ID errors under-mapped
تسجيل الدخول، إنشاء حساب، تسجيل الخروج
When OTP send limits are hit or national ID/mobile already exists, the user needs a specific actionable message.
What’s wrong: loginSendOTP collapses most failures to generic network error (no OTPExceededLimits = 20). registerUserOTP handles mobile duplicate (19) but not national-ID duplicate (18). Forgot-password OTP paths have similar generic fallbacks.
Backend returns distinct codes: OTPExceededLimits (20), NationalIdAlreadyExist (18), MobileNumberAlreadyExist (19). Website surfaces these in UI.
W8-UX-007
text auth P2
New-password step says “enter your new password” vs Website “create new password”
تسجيل الدخول، إنشاء حساب، تسجيل الخروج
Password recovery is a regulated flow; step labels must match
What’s wrong: forgot_password_new_password_subtitle EN Enter your new password; AR ادخل كلمة المرور الجديدة
Website: قم بإنشاء كلمة المرور الجديدة (forget-password.component.html:104)
W8-UX-005
text auth P2
Register link says “إنشاء حساب جديد” instead of Website “تسجيل جديد”
Consistent acquisition CTA across platforms
What’s wrong: LoginView link: إنشاء حساب جديد
Website login header link: تسجيل جديد (login.component.html:13)
W4-AUTH-F007
auth P2
Register payload omits optional email field
تسجيل الدخول، إنشاء حساب، تسجيل الخروج
Registration may collect email for receipts and auth emails when the product asks for it.
What’s wrong: AuthenticationInteractor.registerUser has "email" commented out in params; presenter holds email state but it is never sent.
Backend RegisterUserInput accepts optional Email; Website register form can supply it.
W8-UX-022
text auth P2
Signup OTP instructions differ from Website register OTP
تسجيل الدخول، إنشاء حساب، تسجيل الخروج
OTP step must reference mobile number consistently
What’s wrong: SignupOTPView: قم بادخل الرمز المرسل على رقم الجوال (grammar: بادخل)
Website register OTP: ادخل رمز التحقق المرسل على جوالك (register.component.html:60,215)
W4-AUTH-F005
auth P2
Website biometric login/registration not in SwiftUI Authenticator
تسجيل الدخول، إنشاء حساب، تسجيل الخروج
Returning bidders on supported devices can unlock with Face ID / fingerprint instead of OTP on every visit.
What’s wrong: SwiftUI LoginView / AuthenticationPresenter have no biometric login or post-login registration prompt. BiometricService.swift exists for local device unlock only. Website has full BiometricAuthService + LoginApplicationUserService.authenticateWithBiometric() and registration prompt after OTP login.
Website prompts for biometric credential registration after first OTP login (when enabled) and supports passwordless biometric re-login via backend BiometricAuthService.
W8-UX-002
text auth P2
Wrong password/National ID error text does not match Website
تسجيل الدخول، إنشاء حساب، تسجيل الخروج
User must see the same denial reason Website shows after failed login OTP send
What’s wrong: WrongUserOrPass → AR كلمة المرور أو اسم المستخدم خاطئ; EN Password or username is wrong
Website AR: خطأ في رقم الهوية أو كلمة المرور; EN (en-US.json): Account information is incorrect
W8-UX-009
text auth P3
English auth buttons alternate between Login and Sign In
تسجيل الدخول، إنشاء حساب، تسجيل الخروج
Single verb for authentication across app
What’s wrong: Login = Login; go_to_login / profile_login_btn / home_login = Sign In
Website en-US.json: Login = Login, login = login (lowercase in places)
W4-AUTH-F008
no-website auth P3
SwiftUI login OTP skips standalone ValidateOtpForLogin call
تسجيل الدخول، إنشاء حساب، تسجيل الخروج
Some clients validate OTP in a separate step before exchanging tokens.
What’s wrong: LoginOTPView.confirmOTP() calls presenter.login() directly. validateOtpForLogin exists but is marked UIKit-only and unused in SwiftUI.
Backend validates OTP inside Login when ignoreOtp=false; separate ValidateOtpForLogin endpoint exists but is optional. Website also posts OTP directly to Login without a separate validate call.

Notifications · الإشعارات (7)

IDTagsPriScenario — what happens / what’s wrongShould be (correct)
W4-AUTH-F004
W4-NOTIF-001
W4-NOTIF-002
W1-HUB-002
signalr auth notifications P1
No notifications / PropertyForUser hub joins after login
الإشعارات، التحديثات المباشرة
In-app notifications and user-scoped property/rep updates should arrive after login without opening a lot first.
What’s wrong: In-app notification list stays stale until refresh; live UserNotification never arrives; rep updates may miss until opening a lot.
On connect when logged in: join notifications + PropertyForUser + AuctionForUser groups; handle UserNotification.
W4-NOTIF-003
notifications P1
Push tap ignores notificationId (no mark-read)
الإشعارات، فتح الإشعار
Tapping a push should mark that notification read then deep-link, so unread badges stay accurate.
What’s wrong: Opening from push leaves the item unread in the in-app list/badge.
Parse notificationId from FCM data; mark-read API then navigate.
W4-NOTIF-005
notifications P2
Foreground FCM shows system banner only — no in-app notification UX
الإشعارات
Active app should surface notification content consistent with Website toastr + routing affordance
What’s wrong: willPresent returns [.banner, .badge, .sound]; does not update list, badge, or offer tap routing until user taps system banner
Website hub path shows custom toastr with body text and tap → redirect
W4-NOTIF-004
signalr notifications P2
Home unread badge only refreshes on Home appear
الإشعارات
Bell badge on home should reflect new notifications while user browses other tabs
What’s wrong: fetchUnreadNotificationCount() called from HomeView.onAppear only; not tied to push or SignalR
Website updates badge on hub event and on header dropdown open
W8-UX-013
text notifications P2
iOS notifications empty view has no “browse auctions” button
الإشعارات
Empty notifications should guide user back to discovery
What’s wrong: NotificationsView empty state: icon + title + description only
Website app-no-data button تصفح المزادات الآن → /home (notifications.component.html:49-51)
W4-NOTIF-008
notifications P2
List fetch auto-marks returned page as read (all clients)
الإشعارات
Opening notification list/dropdown should not silently clear unread state for unseen items
What’s wrong: Same as Website — GetNotifications backend marks fetched IDs read via MarkListAsRead
Product decision: either explicit mark-read on tap only, or document auto-read-on-fetch
W8-UX-014
text notifications P3
Empty notifications title spacing/hamza differs slightly from Website
الإشعارات
Polished AR copy consistency
What’s wrong: no_notifications_title AR لاتوجد إشعارات حتى الآن
Website title لا توجد اشعارات حتى الآن (notifications) / لا توجد اشعارات حتى الآن (no-data title)

Profile · الملف الشخصي (9)

IDTagsPriScenario — what happens / what’s wrongShould be (correct)
W4-PROF-002
text bidding privacy P1
Bidder name display preference missing on iOS
إعدادات العرض، اسم المزايد
Users choose how their name appears on the bidder board (full/masked/code).
What’s wrong: No preference setting; board privacy choice only changeable on Website.
Preference UI + API like Website; board reflects choice.
W4-PROF-003
W7-ACT-001
W7-ACT-002
W7-ACT-009
P1
Favorites / My Bids / Interests limited to Property category
اهتماماتي، مزايداتي، التصنيفات
Multi-category favorites and activity (camels, vehicles, etc.) match Website EndUser product; counts per category should be available.
What’s wrong: Only real-estate (Property) items appear; no category tabs/counts for other types.
Load all relevant auctionItemTypes; show per-category counts like Website.
W4-PROF-001
calculations P1
Profile image upload not implemented
الملف الشخصي، الصورة
Users can upload/change avatar on Website EndUser profile.
What’s wrong: No avatar upload control on iOS profile.
Upload/change profile image via same APIs as Website.
W4-PROF-006
calculations dto P2
`regionId` not decoded; address edit pre-fill fragile
الملف الشخصي، حسابي
Region is required to cascade city picker when editing national address
What’s wrong: `UpdateAddressView.onAppear` tries to infer region from `saudiCitiesArr.first(where: cityID)` — fails if cities not pre-loaded
Backend returns `RegionId` on `GetUserInformationOutput`; Website pre-selects region in address form via `regionId` on user DTO
W4-PROF-005
calculations dto P2
Auction participation stats not shown on iOS profile home
الملف الشخصي، حسابي
Profile sidebar communicates bidding history at a glance (, )
What’s wrong: Backend returns stats; iOS decodes into `ProfileResult` but `ProfileHomeView` menu has no stat strip
Website `profile.component.html` shows counts under avatar area
W4-PROF-004
P2
Category interest counts not fetched on iOS
الملف الشخصي، حسابي
Favorites hub shows aggregate counts per category so users know where their saved lots live
What’s wrong: No URL constant or interactor for count endpoint; My Interests header has no per-category totals
Website calls `GetWebsiteUserInterestsCount` on favorites init; `getAuctionCount()` sums enabled categories
W4-PROF-007
P2
Preferences / biometric settings absent on iOS (platform subset)
الملف الشخصي، حسابي
Central place for bidding-related preferences (name display; WebAuthn biometric on Website)
What’s wrong: `ProfileRouter` has no preferences route; biometric block is Website-only (`BiometricAuthService`)
Website preferences tab for bidder-name setting; biometric where browser supports WebAuthn
W4-PROF-008
P3
Hardcoded KYC “ID issue place” on iOS
الملف الشخصي، حسابي
Display field for where identity document was issued
What’s wrong: `PersonalInfoView` `singleRow` hardcodes Saudi Arabia string
Website main-info does not show this field; backend has no dedicated column — field is iOS-only filler
W4-PROF-009
P3
My Interests status logic legacy vs canonical (known Q3 debt)
الملف الشخصي، حسابي، مزايداتي، اهتماماتي
User must see accurate lot state (live vs upcoming vs closed vs committee) on favorites list
What’s wrong: `MyInterestsItemCardView.cardLiveType` documents website-parity legacy path; `InterestedItem` lacks canonical status fields present on home cards
Website favorite cards + backend projections should align with counter-spec canonical status once Q3 fields added to `GetWebsiteUserInterests` payload

Property Details · تفاصيل العقار (9)

IDTagsPriScenario — what happens / what’s wrongShould be (correct)
W3-DET-001
signalr bidding P1
Hidden lot (visible=false) not dismissed on first load
تفاصيل العقار
If API says a lot is not visible, the user must leave the screen (Website does on first load).
What’s wrong: Opening a hidden lot still shows detail until a later SignalR hide event.
Leave/dismiss when initial API returns visible == false.
W3-DET-003
W3-DTO-016
dto P1
Selling-agent contact tab missing on lot detail
وكيل البيع، تواصل
Users need selling-agent contact (mobile / WhatsApp) on lot detail like Website.
What’s wrong: No agent contact tab or mobile/WhatsApp fields on iOS detail.
Agent contact tab with mobile fields matching Website.
W3-DET-005
P2
iOS hides auction live broadcast for Online auctions only
تفاصيل العقار
Some online auctions still stream opening/closing ceremonies via auctionLiveVideoLink
What’s wrong: PropertyCarouselView.hasLiveStream requires auctionTypeID != 1 before showing auctionLiveVideoLink
Website shows live tab whenever auctionLiveVideoLink is non-empty (no online-type exclusion)
W3-DET-006
text dto P2
iOS map ignores locationLink when lat/lng are zero
تفاصيل العقار
Some lots only have Google embed URL without normalized coordinates
What’s wrong: MapViewSection shows "no coordinates" placeholder unless latitude/longitude != 0
Website location tab renders app-zayid-google-map-iframe from propertyDetailsOutputDTO.locationLink
W3-DET-007
text P2
Parcel vs plan number labels swapped vs Website
تفاصيل العقار
number = parcel (قطعة), plotNumber = subdivision plan (مخطط) in Saudi deed context
What’s wrong: iOS labels plotNumber → "رقم القطعة", number → "رقم العقار"
Website: number → "رقم القطعة", plotNumber → "رقم المخطط"
W3-DET-004
W3-DTO-012
dto P2
Virtual tour URL missing on iOS property detail
جولة افتراضية
Lots with virtualTourUrl should expose a 3D/virtual tour entry like Website.
What’s wrong: No virtual tour link/viewer on iOS.
Decode virtualTourUrl and show tour entry.
W3-DET-010
P2
Website location tab split from property tab; iOS merges location into property tab
تفاصيل العقار
Location (map + boundaries) is a first-class navigation destination on Website
What’s wrong: All location rows + map live inside tab 1 "Property details"
Website active3 tab 2 "معلومات عن الموقع" is separate with richer boundary layout
W3-DET-008
dto P3
headerImage never used in iOS media carousel
تفاصيل العقار
Optional hero image distinct from gallery thumb
What’s wrong: Model decodes headerImage but carousel uses image + imagesAndVideos only
Website can promote header asset in gallery context
W3-DET-009
P3
Interest count (numberOfInterests) not displayed on iOS
تفاصيل العقار، مزايداتي، اهتماماتي، تم البيع
Social proof — how many users favourited the lot
What’s wrong: Star toggle updates isAuctionItemInterested locally; count not shown in UI
Website item card surfaces interest count after toggle

Representatives · الممثلين (2)

IDTagsPriScenario — what happens / what’s wrongShould be (correct)
W5-REP-003
W5-REP-004
bidding P1
Change-representation still offered after user already bid
تغيير صفة الممثل، تأكيد المزايدة
After bidding, representation type must not change (server status 77).
What’s wrong: "تغيير صفة الممثل" still shown after user has bids on the lot.
Hide change-rep when isUserHasAnyBidOnProperty (Website gate).
W5-REP-002
P2
iOS shows “change representation” on rejected requests; Website hides it
نوع الممثل، ممثل لنفسه، ممثل لشخص
After an agent rejects a representation request, the product should steer the user to agent contact / resubmit flow defined by Website — not offer a change button that implies a clean resubmit path when Website blocks it in the info panel.
What’s wrong: RejectedRepresentationView always shows “change representation role” when the lot is not terminal-closed.
Website info tab: تغيير صفة التمثيل only when !result.isUserHasAnyBidOnProperty && !isRequestRejected (real-estate-details.component.html ~1769). isRequestRejected is true when any detail sub-struct has requestStatus/requestStatusId = Rejected (3).

Onsite Registration · التسجيل الحضوري (10)

IDTagsPriScenario — what happens / what’s wrongShould be (correct)
W5-ONSITE-002
onsite P0
Company / MOA onsite uploads one legacy file instead of required set
ممثل لشركه، السجل التجاري، عقد التأسيس
Company representatives must supply each document the selling agent configured (CR, agency, articles, etc.).
What’s wrong: Only one generic PDF is requested/sent; commercial registration or other required files missing after submit.
Separate uploads for each auction-required company/MOA file, matching Website.
W5-ONSITE-003
onsite P0
Onsite form ignores auction-conditional document rules
التسجيل الحضوري، المستندات المطلوبة
Each auction declares which representative documents are mandatory. The client must block submit until those files are present.
What’s wrong: User can submit with only name/CR/one PDF even when auction requires agency or other files; then gets opaque backend errors.
Validators follow auction flags (like Website); submit blocked until required files attached.
W5-ONSITE-001
onsite P0
Self-representation onsite sends wrong document payload
التسجيل الحضوري، ممثل نفسه
Self-representation ("ممثل نفسه") onsite registration must attach auction-required authorization documents under the correct backend field group.
What’s wrong: Selecting "ممثل نفسه" may submit without the required ownership/authorization files, or registration fails/agent sees empty attachments.
PersonalSelf posts documents under on-his-own-behalf fields; required files appear in agent view like Website.
W5-ONSITE-008
auth onsite P1
idNumber may fall back to JWT userData GUID
رقم الهوية، التسجيل الحضوري
National ID must be the real idNumber, never a GUID fallback.
What’s wrong: Submitted id looks like a GUID or wrong identifier; registration fails validation.
Always send real national ID from profile/auth claims.
W5-ONSITE-007
text onsite P1
Onsite duplicate/conflict errors collapsed to generic message
التسجيل الحضوري، خطأ
Users need specific duplicate/conflict messages to fix registration issues.
What’s wrong: All failures show the same generic error.
Map known statuses to Website-equivalent Arabic messages.
W5-ONSITE-005
auth onsite P1
Onsite register CTA shown when logged out
التسجيل الحضوري، تسجيل الدخول
Onsite registration requires login; guests should be prompted to log in first.
What’s wrong: Logged-out user sees register CTA that leads to broken/empty flow.
Hide CTA or route to login then form, like Website.
W5-ONSITE-006
onsite P1
Onsite Step 1 allows advance with zero properties selected
التسجيل الحضوري، اختيار العقارات
User must select at least one property before continuing registration.
What’s wrong: Next enabled with empty selection.
Block advance until ≥1 property selected.
W5-ONSITE-004
onsite P1
Personal-agent path sends no representative attachment files
ممثل لشخص، المستندات
Personal-agent onsite registration must upload required agency/authorization files.
What’s wrong: Personal-agent submit succeeds without attachments or fails compliance checks.
Required personal-agent files collected and posted like Website.
W5-ONSITE-010
onsite P2
Cheque date not rejected when after today
التسجيل الحضوري
Post-dated cheques should not fund onsite deposit.
What’s wrong: AddEditChequeSheetView.tryFinish requires date present but allows future dates.
Website CustomControlValidators.notAfterCurrentDateTimeValidator on checkDate.
W5-ONSITE-009
onsite P2
Finished-auction gating uses dates only, not auctionStatus
التسجيل الحضوري
Registration must close when auction is finished (auctionStatus = 3).
What’s wrong: shouldShowOnsiteButton uses isClosed + computed auctionLiveType; does not read auctionStatus == 3.
Website hides CTA when auctionStatus == 3 regardless of hint drift.

Hybrid Plus · هجين بلس (4)

IDTagsPriScenario — what happens / what’s wrongShould be (correct)
W9-HP-002
timer hybrid-plus P1
Auction lot cards keep stale parent endDate after parent extend
جاري، إنتهى المزاد، قائمة العقارات
After parent auction extend/end, every lot card must re-evaluate Finished using the new parent cap.
What’s wrong: On auction properties tab, cards still show "جاري" after parent ended; only header may update.
All HP cards flip status without leaving screen (Website binds parent into each card).
W9-HP-004
signalr hybrid-plus P2
AuctionData updates auction header only; Website refetches items
قائمة العقارات، جاري
Parent AuctionData changes should refresh lot list fields, not only the auction header.
What’s wrong: Header updates; property rows stay stale.
Refetch properties or merge parent dates into every row like Website.
W9-HP-003
text timer hybrid-plus P2
Detail shows lot-closed copy instead of parent-expired إنتهى المزاد
إنتهى المزاد
When parent evening cap expires, detail must show parent-expired ended copy like cards.
What’s wrong: Detail timer strip shows generic lot-closed text; cards already know isParentExpired.
Same parent-cap branch as cards: "إنتهى المزاد".
W1-TIME-F002
W9-TYPE-002
no-website timer bidding P2
Hybrid Plus confirm gate missing timerIsActive (Website)
تأكيد المزايدة، جاري
Near timer zero, Website also requires the local timer to be active before confirm; iOS may allow a narrow race before extend event.
What’s wrong: Confirm briefly available when timer already hit zero before parent extend arrives.
HP confirm requires timerIsActive like Website.

Auction Types · أنواع المزادات (2)

IDTagsPriScenario — what happens / what’s wrongShould be (correct)
W5-HYB-001
W1-TIME-F001
W9-TYPE-001
signalr bidding onsite P1
Online bid UI shown on Attended (hall-only) auctions
مزاد حضوري، تأكيد المزايدة
Attended auctions are display-only online; hall staff take bids. End users must not see +/- or confirm bid controls.
What’s wrong: On type "حضوري" auctions, user still sees increment buttons and "تأكيد المزايدة".
Bid chrome hidden (Website *ngIf=!isAttended); price can still update via SignalR.
W9-TYPE-003
text bidding hybrid-plus P2
Classic Hybrid hides date label with HP-only isClosed==null rule
يبدأ، ينتهي، هجين
Classic Hybrid (type 3) is date-driven like Online; users expect start/end labels.
What’s wrong: Date labels hidden incorrectly on Hypred lots.
Limit that hide rule to auctionTypeID == 4 (HP only).

Kingdom Hub · مزادات المملكة (6)

IDTagsPriScenario — what happens / what’s wrongShould be (correct)
W6-LIST-001
W6-DET-005
W6-LIST-007
P1
Kingdom property favorites not implemented
مزادات المملكة، المفضلة
Website lets users favorite Kingdom catalog items; iOS cannot toggle or list them.
What’s wrong: No heart/favorite on Kingdom item; profile has no Kingdom favorites.
Toggle + profile list + API like Website.
W6-DET-004
P2
iOS missing sold-out / final-price display
مزادات المملكة، جاري، قادم
When is true, catalog shows final price or “لا توجد مزايدات” when
What’s wrong: `soldOut` and `finalPrice` exist on `KingdomAuctionItem` but no view renders them in cards or `PropertyDetailsView`
Mirror Website `kingdom-property-card.component.html` sold-out block
W6-LIST-005
P2
iOS opens on المزادات tab; Website kingdom_auctions redirects to items
Landing tab sets whether users first see catalog properties or catalog auctions — product default is properties on Website.
What’s wrong: currentItemType: ItemType = .auctions on presenter init.
Website routing: { path: '', redirectTo: 'items', pathMatch: 'full' } under kingdom_auctions.
W6-DET-003
text P2
iOS shows `cityName` instead of `address` (city + neighborhood)
مزادات المملكة، جاري، قادم
Website labels location “المدينة” but displays = — users see both city and حي
What’s wrong: `PropertyDetailsView` and `PropertyCardViewWithButton` render `property.cityName` only
Display `address` when present, else fall back to `cityName` (matches Website card HTML `AuctionItem.address`)
W8-STAT-005
text P2
Kingdom catalog cards never show sold state or sale price
تم البيع
Kingdom items can be soldOut with finalPrice; Website shows sale value and favorites show تم البيع
What’s wrong: KingdomAuctionsSwiftUIView property cards render status timers from statusId only; no soldOut branch. Model carries soldOut/finalPrice from API
Website kingdom-property-card shows سعر البيع with finalPrice when soldOut; favorites use تم البيع
W6-LIST-006
P3
iOS map marker fetch may not request all cities
مزادات المملكة، جاري، قادم
Map view should show every city cluster matching current filters, not a truncated page.
What’s wrong: getMapCitiesList sends status/types/cities/agents/authorities/name only — no limit field.
Website getMapCitiesList sets limit: -1 explicitly to fetch all matching cities.

My Activity · نشاطي (2)

IDTagsPriScenario — what happens / what’s wrongShould be (correct)
W7-ACT-003
W7-ACT-004
signalr P1
No live refresh on Interests / My Bids lists
اهتماماتي، مزايداتي
Favorite and My Bids cards should update live when prices/status change, like Website.
What’s wrong: Lists stay stale until pull-to-refresh; new bid not reflected on My Bids until reopen.
Join property groups or refetch on relevant events.
W7-ACT-014
text P3
Website favorites empty-state copy differs slightly from iOS interests
مزايداتي، اهتماماتي، تم البيع
Consistent empty-state guidance when no favorites.
What’s wrong: iOS empty copy in MyInterestsSUIView (Figma-driven).
Website: title لايوجد أصول مضافة في قائمة اهتماماتك, CTA تصفح المزادات الآن.

Add Property · إضافة عقار (6)

IDTagsPriScenario — what happens / what’s wrongShould be (correct)
W7-ADD-001
auth P1
Guests cannot open Add Property
إضافة عقار، تقديم عقار
Website header exposes submit-property to guests; iOS hides it behind login-only navigation.
What’s wrong: Logged-out user cannot find/open Add Property form.
Public entry or login-then-form matching Website /submitProperty.
W7-ADD-004
P2
Add Property submit skips Saudi phone validation used elsewhere
إضافة عقار
Invalid phone numbers should be rejected before ops receives the lead
What’s wrong: AddPropertyFormView shows 9-digit UI error (phoneError) but submitPropertyRequest() only guards !trimmedPhone.isEmpty. No Utils.isValidSaudiPhoneNumber call (used in SendTechnicalSupportView / legacy UIKit VC)
Website submitPropertyForm uses CustomControlValidators.mobileNumberValidator on phoneNumber; invalid numbers block submit
W7-ADD-003
dto P2
Ops external note (الملاحظات) missing from iOS request history
When ops updates a request they may leave an external note visible to the submitter explaining next steps or rejection reason
What’s wrong: AddPropRequestItem decodes externalNote but AddPropertyRequestCard.detailsSection never renders it
Website submit-property-requests.component.html shows "الملاحظات" with {{propertyRequest.externalNote}}. Backend GetPropertyRequestsList returns ExternalNote
W7-ADD-002
text P2
Property request status labels differ from Website for all three states
إضافة عقار
User reads badge text to know whether ops confirmed listing, rejected it, or is still reviewing
What’s wrong: AddPropertyRequestCard.statusStyle: 0/default → "تحت المراجعة", 1 → "تم المراجعة", 2 → "لم يتم التأكيد"
Website getStatusEnumLabel: 0 → "قيد المعالجة", 1 → "تم تأكيد الإدراج", 2 → "لم يتم تأكيد الإدراج". Backend enum: PropertyRequestStatusEnum InProgress=0, Confirmed=1, NotConfirmed=2
W7-ADD-006
text P3
Request history date format omits time vs Website
إضافة عقار
User may need timestamp when multiple requests submitted same day
What’s wrong: formatDate outputs dd MMM yyyy (Arabic locale), no time component
Website pipe date:'dd/MM/yyyy HH:mm:ss' after convertDateToLocalInObject
W7-ADD-005
P3
Successful property submit dismisses without confirmation message
إضافة عقار
User expects explicit acknowledgment that the request was received
What’s wrong: On success, AddPropertySUIView onChange(of: presenter.submitSuccess) calls dismiss() only — no success alert/snackbar
Website CreatePropertyRequest success → snackbar "تم الارسال بنجاح" then form reset

Terminology & Copy · المصطلحات والنصوص (14)

IDTagsPriScenario — what happens / what’s wrongShould be (correct)
W8-TERM-001
text calculations bidding P1
Bid screen RETT label wrong vs Website
قيمة التصرفات، ضريبة التصرفات العقارية
Regulated RETT fee label must match Website wording by attribution type.
What’s wrong: Shows "ضريبة التصرفات العقارية" where Website shows "قيمة التصرفات" (or wrong variant).
Mirror Website label by attributionTypeId.
W8-STAT-001
text P1
Kingdom map status typo جـاري (kashida)
جاري، خريطة المزادات
Active status must read "جاري" without kashida corruption.
What’s wrong: Map sheet shows "جـاري".
"جاري" like elsewhere/Website.
W8-STAT-003
text P1
My Bids uses مباشر/قريباً instead of جاري/قادم
مزايداتي، جاري، قادم
Canonical status words across the app are "جاري" and "قادم".
What’s wrong: My Bids badges say "مباشر" / "قريباً".
"جاري" / "قادم" like Website canonical chips.
W8-STAT-002
text P1
My Interests shows منتهي when sold instead of تم البيع
اهتماماتي، تم البيع، منتهي
Sold lots must show sold copy, not generic ended.
What’s wrong: Sold interest shows "منتهي" while Website shows "تم البيع".
Match Website sold copy.
W8-UX-017
W8-UX-019
W8-UX-018
text P1
Representative type labels diverge from Website regulated names
ممثل لنفسه، ممثل لشخص، ممثل لشركه، ممثل بموجب عقد التأسيس
Representation type names are regulated product copy and must match Website exactly.
What’s wrong: iOS shows shortened/different labels (e.g. "ممثل شخص/شركة") vs Website full set.
Use Website: ممثل لنفسه / ممثل لشخص / ممثل لشركه / ممثل بموجب عقد التأسيس.
W8-UX-010
text P2
Account tab title uses “My Account” not “Personal File”
الملف الشخصي
Profile area naming should match Website navigation
What’s wrong: profile_home_title AR حسابي, EN My Account
Website profile nav first item: الملف الشخصي; breadcrumbs use الملف الشخصي (main-info.component.ts:143)
W8-UX-012
no-website text P2
iOS exposes “Security Settings” row Website does not list
الشاشة نفسها في التطبيق
Profile menu should mirror Website capabilities and naming
What’s wrong: profile_row_security AR اعدادات الامان, EN Security Settings
Website embeds change-password inside main-info (تغيير كلمة المرور); separate security hub not in sidebar
W8-STAT-007
text P2
Live auction detail ended banner omits hamza on إنتهى
إنتهى المزاد
Website consistently uses إنتهى المزاد for parent-auction-ended strips
What’s wrong: AuctionSUIView uses auction_closed_label → AR "انتهى المزاد"
Website down-counter.component.html, item-detailed-card use إنتهى المزاد; Home card uses home_card_auction_ended = إنتهى المزاد
W8-TERM-005
text bidding P2
opening_price_label truncates Website opening-price wording
الشاشة نفسها في التطبيق
Cards and interest lists must show the full statutory label السعر الافتتاحي.
What’s wrong: opening_price_label = سعر الافتتاح (missing definite article + final ي). Used in MyInterestsItemCardView, AuctionPropertyCardView.
Website: السعر الافتتاحي (item-detailed-card, translations "Opening Price": "السعر الافتتاحي").
W8-UX-011
no-website text P2
Personal-info menu row label differs from Website
الملف الشخصي
Same menu item must read the same on both clients
What’s wrong: profile_row_personal_info AR المعلومات الشخصية, EN Personal Information
Website: الملف الشخصي (profile sidebar)
W8-TERM-002
no-website text calculations P2
SwiftUI VAT row adds “نسبة” prefix Website does not use
VAT line on bid cost breakdown should read like Website’s fee disclosure — label + percentage in parentheses.
What’s wrong: SwiftUI uses نسبة ضريبة القيمة المضافة (%@) in details/cost sheet.
Website: ضريبة القيمة المضافة + ({{ result?.taxes }}%) as separate inline elements.
W8-UX-020
text P2
Terms-not-accepted error uses generic message, not Website validation tone
الشاشة نفسها في التطبيق
User must accept terms before submitting representation
What’s wrong: AuctionRepSetupPresenter error يجب الموافقة على الشروط والأحكام; checkbox uses correct regulated line
Website blocks submit via form; regulated checkbox أقرّ باطلاعي على الشروط والأحكام وأوافق عليها (same on iOS checkbox) — inline errors on incomplete rep data use specific toasts e.g. من فضلك قم بإدخال بيانات ممثل لشركة كاملة
W8-UX-021
text P3
password_rule_ keys defined twice in EN with different text
الشاشة نفسها في التطبيق
Password rules shown during signup/reset must be unambiguous
What’s wrong: en.lproj: first block At least 8 characters … later 8 characters long without white spaces (overwrites)
Website password restrictions / use complex password single canonical rule text
W8-TERM-009
text calculations wallet P3
SwiftUI blocked-transactions list omits Website table headers
الشاشة نفسها في التطبيق
Wallet blocked section identifies which lots hold entry fees — Website table headers set expectations.
What’s wrong: WalletHomeView / BlockedTransactionRow shows item name + amount only; no section headers.
Website wallet table: بنود تمت المزايدة عليها + column عربون دخول البند (wallet.component.html ~L394–395).

DTO / Decode · نماذج البيانات (8)

IDTagsPriScenario — what happens / what’s wrongShould be (correct)
W3-DTO-007
calculations bidding dto P1
bidNumber typed as Decimal on property detail
عدد المزايدات
Bid count is a count, not money; wrong type can break display/logic.
What’s wrong: Bid count display or logic looks wrong/fractional.
Integer bid count matching Website.
W3-DTO-005
calculations bidding dto P1
Large SAR prices lose precision (non-Decimal list fields)
السعر، المزايدة
Large lot prices must display exact SAR amounts without floating-point drift.
What’s wrong: Very large prices show rounded/off-by-halalah values vs Website.
Decimal-safe money fields matching backend/Website.
W3-DTO-004
signalr bidding dto P1
Required itemType on Property SignalR can fail whole event
التحديثات المباشرة
Partial Property SignalR payloads must not crash decode and drop the entire live update.
What’s wrong: Live property updates sometimes stop applying (stale price/status) when itemType missing.
Decode resilient like Website; event still applies.
W3-DTO-003
dto P1
soldOut ?? false treats unknown as available
تم البيع، اهتماماتي
Unknown sold state must not be shown as available; null soldOut is not the same as false.
What’s wrong: Items with unknown sold flag appear as still available / wrong status.
Preserve unknown vs sold; display matches Website when soldOut is null/true.
W3-DTO-015
dto P2
iOS “on his own behalf” rep model includes unused company fields
الشاشة نفسها في التطبيق
Self-representation requires national ID + permit files, not company CR.
What’s wrong: onHisOwnBehalfRepresentativeDetails declares companyName, crNo.
Backend/Website: rejectionReason, requestStatusId, two file attachments only.
W3-DTO-017
calculations dto onsite P2
Onsite cheque amount type differs across clients
التسجيل الحضوري
Attended auction registration validates cheque amounts.
What’s wrong: OnsiteBidderChequeModel.checkAmount: String?.
Website CheckDetailsDTO.checkAmount: number.
W3-DTO-014
dto P2
Website AuctionItemOutputDto.finalPrice has no backend source
الشاشة نفسها في التطبيق
Final hammer price after sold lot — display only.
What’s wrong: iOS list model has no finalPrice (matches backend).
Backend AuctionItemOutputDto has no FinalPrice; Website adds finalPrice: number.
W3-DTO-018
dto P3
Sold-items count uses inconsistent names and types
الشاشة نفسها في التطبيق
Auction header badge “sold X of Y lots”.
What’s wrong: Detail: soloutItemsCount: String?; home: soloutPropertiesCount: Int?; backend field commented out.
Single canonical key and numeric type from backend.

P0 smoke list

Run these first. Open each ID in its module section for full steps.

  1. Onsite Registration / RepresentativesCompany / MOA onsite uploads one legacy file instead of required set (W5-ONSITE-002)
  2. Onsite RegistrationOnsite form ignores auction-conditional document rules (W5-ONSITE-003)
  3. Onsite Registration / RepresentativesSelf-representation onsite sends wrong document payload (W5-ONSITE-001)
  4. Live Bidding / Property Details / DTO / DecodeSpecialty lots (camel/vehicle/etc.) crash or blank property detail (W3-DTO-002)
  5. Wallet / DTO / DecodeWallet history truncates fractional SAR amounts (W3-DTO-001)
Pass rule: All P0 scenarios pass; no critical/blocker defects left open on P1 for the release slice you are signing.

Defect report template

  1. Surface: iOS (and Website comparison if relevant)
  2. Scenario ID / issue code from this guide (e.g. W3-DTO-001)
  3. Steps and expected vs actual
  4. Account (role only — not password)
  5. Auction / property used (name or id)
  6. Build (iOS version / commit if known)
  7. Screenshot or short recording
0 / 0 tests checked