Skip to content

Feat/api contract alignment - #31

Merged
laithanhhung merged 2 commits into
devfrom
feat/api-contract-alignment
Aug 6, 2026
Merged

Feat/api contract alignment#31
laithanhhung merged 2 commits into
devfrom
feat/api-contract-alignment

Conversation

@laithanhhung

@laithanhhung laithanhhung commented Aug 6, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • Added restaurant claims filing and claims history views, including pagination, statuses, validation, and error handling.
    • Added server-synchronized cart drafts for signed-in users, with local-cart support and sync status, retry, and validation feedback.
    • Added route hub suggestions, coordinate warnings, order counts, stop-limit enforcement, and assignment guidance.
    • Added localized map-unavailable messaging while preserving manual location entry.
  • Bug Fixes

    • Improved API and form error translation, including detailed handling for unknown validation errors.
    • Added stronger client-side validation for catalog, profile, delivery, checkout, quantities, claims, URLs, tax codes, and coordinates.
    • Prevented invalid cart quantities, checkout attempts, route moves, and claim values.

laithanhhung and others added 2 commits August 6, 2026 15:01
`core.autocrlf=true` writes CRLF into a Windows working copy while Prettier
defaults to LF, so `prettier --check` failed on ~200 files nobody had touched
and `npm run precheck` could never go green.

`.gitattributes` pins the checkout to LF on every platform; `endOfLine: "auto"`
tolerates a working copy that predates it. No file contents are reformatted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…esponse

The web client was built against `docs/04-api-design.md`, which the backend's
own guide says predates the code. Where they disagreed the doc won here, so
requests were sent that the server always refused and refusals arrived as
English prose or as nothing at all. Every rule below was read off the
FluentValidation validator or handler that actually runs.

Response handling
- `resolveApiError()` replaces the string-only path: it returns the localized
  message plus the code, status and whether the failure was recognized.
  `describeApiError()` stays a thin wrapper, so no call site changed.
- An unrecognized failure now keeps its code in the sentence. Previously an
  unmapped code fell through to the HTTP category, so two different 403s read
  identically and the one identifying detail was dropped.
- Field errors: an unmapped rule is framed as a Vietnamese sentence with the
  server's words as the detail, instead of being shown as raw English.
- FluentValidation's *default* messages (which interpolate the property name
  and the length typed) are matched by pattern — they can never match a
  literal table, and they are most of what the API sends.
- Error codes swept out of every `Error.*` call site: 122 -> 201 mapped,
  covering the Hub / Logistics / Procurement half that had none. Fixed two
  codes that are never sent (`REFRESH_TOKEN_INVALID`, `RATE_LIMITED`) against
  the ones that are (`TOKEN_INVALID`, `TOO_MANY_REQUESTS`).
- Admin CRUD dialogs pin `details[]` onto the offending control, so "check the
  highlighted fields" finally highlights one.

Client-side validation, per validator
- Tax profile: three fields are `NotEmpty` and the tax code has a format
  (`^\d{10}(-\d{3})?$`) that was not checked at all; three limits were wrong.
- Delivery address, business profile, account, products, markets, categories,
  units, packing codes, hubs: limits corrected or added where the form was
  unbounded. Several differ per entity (unit name 100, others 200).
- Order issue: quantity must exceed 0 and may not exceed the line's ordered
  quantity; description is capped at 1000, not 500.
- Cart: minimum order quantity and stock are decided from what is on screen,
  named per product, before a draft is created.

Draft orders
The cart is now the server's `Draft` order rather than an in-memory list, so a
reload no longer loses it. Writes are optimistic and serialized; a failed write
re-reads the draft and says why. Signed out the cart stays local and is merged
into the open draft on sign-in.

Claims
`POST /orders/{id}/claims` is restaurant-only and had no screen: filing now
lives on the order it concerns, and the outcomes are listed under the account
area. The status vocabulary moved beside the module that owns claims so the
admin queue and the filer cannot disagree about it.

Fixes found on the way
- Admin create dialog opened without building its form, rendering an empty
  header with no fields and no save button — on every CRUD screen.
- The fields template is projected through `ngTemplateOutlet`, so the
  surrounding `formGroup` never reached the controls (`NG01050`): inputs
  rendered unbound and later fields were left half-built.
- Packing code capacity is a required, bounded decimal; the form treated it as
  optional and sent `undefined`, which binds to 0 and is always refused.
- Route stop limit counts the hub, so a route holds 19 restaurants, not 20.
- Route stop reordering allowed an order the domain refuses (pickups must
  precede dropoffs).
- `/routes/suggestions` was read from a `markets` key the response has never
  carried, so the hubs it suggests — the ones with goods waiting that day —
  were dropped and the origin came from the plain hub list instead.
- The map disappeared silently when no Maptiles key was configured, which is
  what a deployment built without one looks like from the outside.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@laithanhhung
laithanhhung merged commit e280e1c into dev Aug 6, 2026
1 of 3 checks passed
@kody-ai

kody-ai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Code Review Could Not Complete ⚠️

The review failed before suggestions could be generated.

Reason: The configured API key (google_gemini) is out of credits or has hit its billing limit. Top up the account or adjust the plan.

After fixing the issue, comment @kody review on this PR to re-run the review.

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the @kody start-review command at the root of your PR.

  • Validate Business Logic: Ask Kody to validate your code against business rules by adding a comment with the @kody -v business-logic command.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Bug
Performance
Security
Business Logic

Access your configuration settings here.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2716bc20-5670-4ad7-8611-de76bf6f0f54

📥 Commits

Reviewing files that changed from the base of the PR and between 7fb5feb and 111ccce.

📒 Files selected for processing (67)
  • .gitattributes
  • .prettierrc
  • public/i18n/en.json
  • public/i18n/vi.json
  • src/app/core/api/error-codes.spec.ts
  • src/app/core/api/error-codes.ts
  • src/app/core/api/form-errors.spec.ts
  • src/app/core/api/form-errors.ts
  • src/app/core/api/validators.ts
  • src/app/core/maps/location-picker.component.ts
  • src/app/layout/common/draft-order/draft-order.service.spec.ts
  • src/app/layout/common/draft-order/draft-order.service.ts
  • src/app/layout/common/draft-order/draft-order.types.ts
  • src/app/layout/common/favorites/favorites.service.ts
  • src/app/modules/admin/catalog/catalog-admin.service.ts
  • src/app/modules/admin/catalog/categories.component.ts
  • src/app/modules/admin/catalog/market-create.component.ts
  • src/app/modules/admin/catalog/market-edit.component.ts
  • src/app/modules/admin/catalog/packing-codes.component.ts
  • src/app/modules/admin/catalog/product-create.component.ts
  • src/app/modules/admin/catalog/products.component.ts
  • src/app/modules/admin/catalog/units.component.ts
  • src/app/modules/admin/claims/claims-list.component.ts
  • src/app/modules/admin/claims/claims.types.ts
  • src/app/modules/admin/logistics/hubs.component.ts
  • src/app/modules/admin/logistics/logistics-admin.service.ts
  • src/app/modules/admin/logistics/logistics-admin.types.ts
  • src/app/modules/admin/logistics/route-create.component.html
  • src/app/modules/admin/logistics/route-create.component.ts
  • src/app/modules/admin/logistics/route-create.rules.spec.ts
  • src/app/modules/admin/logistics/route-detail.component.html
  • src/app/modules/admin/logistics/route-detail.component.ts
  • src/app/modules/admin/logistics/route-detail.stops.spec.ts
  • src/app/modules/admin/logistics/route-suggestions.spec.ts
  • src/app/modules/admin/logistics/route-suggestions.ts
  • src/app/modules/admin/shared/resource-crud.component.html
  • src/app/modules/admin/shared/resource-crud.component.ts
  • src/app/modules/admin/shared/resource-crud.create.spec.ts
  • src/app/modules/admin/shared/resource-crud.types.ts
  • src/app/modules/cart/cart-line-rules.ts
  • src/app/modules/cart/cart.component.html
  • src/app/modules/cart/cart.component.scss
  • src/app/modules/cart/cart.component.ts
  • src/app/modules/cart/checkout.component.ts
  • src/app/modules/cart/checkout.draft.spec.ts
  • src/app/modules/catalog/catalog.service.ts
  • src/app/modules/catalog/catalog.types.ts
  • src/app/modules/orders/claims.types.ts
  • src/app/modules/orders/confirm-preview.spec.ts
  • src/app/modules/orders/confirm-preview.ts
  • src/app/modules/orders/orders.types.ts
  • src/app/modules/orders/orders.validation.ts
  • src/app/modules/orders/pages/order-detail/order-detail.component.html
  • src/app/modules/orders/pages/order-detail/order-detail.component.ts
  • src/app/modules/restaurant/account-area-nav.ts
  • src/app/modules/restaurant/account-info/account-info.component.ts
  • src/app/modules/restaurant/account-shell/account-shell.component.html
  • src/app/modules/restaurant/account-shell/account-shell.component.scss
  • src/app/modules/restaurant/business-profile/business-profile-form.component.ts
  • src/app/modules/restaurant/claims/claims-list.component.html
  • src/app/modules/restaurant/claims/claims-list.component.ts
  • src/app/modules/restaurant/claims/restaurant-claims.service.ts
  • src/app/modules/restaurant/delivery-addresses/delivery-addresses.component.ts
  • src/app/modules/restaurant/profile.component.ts
  • src/app/modules/restaurant/profile.routes.ts
  • src/app/modules/restaurant/tax-profile/tax-profile-form.component.ts
  • src/styles/styles.scss

📝 Walkthrough

Walkthrough

The pull request aligns frontend validation and API error handling with backend rules, adds persistent draft carts and checkout checks, improves logistics route workflows, and introduces restaurant claim filing and listing. It also adds localized messages and account layout updates.

Changes

API errors and validation

Layer / File(s) Summary
API error localization and validation contracts
src/app/core/api/*, src/app/core/api/validators.ts
API error mappings now preserve codes and statuses, localize validator messages, and support unknown-code details. Backend-aligned tax-code and absolute-URL validators were added.
Shared CRUD and form validation
src/app/modules/admin/shared/*, src/app/modules/admin/catalog/*, src/app/modules/restaurant/*
Shared forms now apply server errors, coordinate limits, numeric maximums, and backend-aligned field lengths.
Localization and fallback messages
public/i18n/*, src/app/core/maps/location-picker.component.ts
English and Vietnamese translations now cover the new validation, cart, route, claim, and API states. Disabled maps show localized guidance.

Persistent draft cart

Layer / File(s) Summary
Server-backed draft order state
src/app/layout/common/draft-order/*
Authenticated carts restore, create, update, merge, reload, adopt, and discard server drafts. Signed-out carts remain local.
Cart quantity and checkout rules
src/app/modules/cart/*, src/app/modules/catalog/*
Cart quantities enforce minimum-order and stock limits. Checkout localizes blockers, prevents invalid orders, and reuses matching drafts.

Logistics

Layer / File(s) Summary
Route suggestions and hub contracts
src/app/modules/admin/logistics/logistics-admin.*, route-suggestions.*
Hub options expose coordinate availability and order counts. Suggestion parsing supports current and legacy response fields.
Route creation constraints
src/app/modules/admin/logistics/route-create.*
Route creation counts the hub in the stop limit, ranks suggested hubs, and blocks planning when the selected hub lacks coordinates.
Assignment and stop ordering
src/app/modules/admin/logistics/route-detail.*
Assignment blockers are displayed. Stop movement prevents pickup and dropoff ordering violations.

Restaurant claims

Layer / File(s) Summary
Claim contracts and filing
src/app/modules/orders/claims.types.ts, src/app/modules/orders/orders.validation.ts, src/app/modules/orders/pages/order-detail/*, src/app/modules/restaurant/claims/*
Shared claim types and validators support claim submission from eligible orders.
Claims navigation and listing
src/app/modules/restaurant/profile.*, src/app/modules/restaurant/account-area-nav.ts
Restaurant profiles now include a guarded claims route and a paginated claims list.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Poem

A rabbit checks each field with care,
Saves cart drafts tucked safely there.
Routes sort hubs, claims now appear,
Localized messages guide the ear.
Validation guards every way—
Hop, hop, ship a safer day!

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/api-contract-alignment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant