# PortalPeople Disabled Postcodes

Magento 2 module to block delivery/shipping for excluded postcodes with:
- Admin CRUD UI
- CSV and XLSX import
- REST API CRUD
- Checkout postcode validation and UX blocking
- Server-side enforcement against client-side bypasses

## Features

- Rule types:
  - `area`: prefix/outcode style match, e.g. `SW1`
  - `exact`: exact postcode match, e.g. `SW1A1AA`
- Store scope support via `store_id` (`0` means all stores)
- Checkout message configurable in admin config
- API rate limiting on public postcode check endpoint
- ACL protected admin/API write operations
- Audit logging (create/update/delete)

## Admin

Menu:
- Stores > Disabled Postcodes > Manage Postcodes

Config:
- Stores > Configuration > General > Disabled Postcodes

Import headers:
- `postcode`
- `match_type` (`area` or `exact`)
- `description` (optional)
- `store_id` (optional, defaults to selected import store)
- `is_active` (optional, `1` or `0`)

## API

Public read/check endpoint:
- `GET /rest/V1/portalpeople/disabled-postcodes/check/{postcode}`

Admin/integration-token endpoints:
- `GET /rest/V1/portalpeople/disabled-postcodes`
- `GET /rest/V1/portalpeople/disabled-postcodes/{id}`
- `POST /rest/V1/portalpeople/disabled-postcodes`
- `PUT /rest/V1/portalpeople/disabled-postcodes/{id}`
- `DELETE /rest/V1/portalpeople/disabled-postcodes/{id}`

## Security

- Admin actions protected by ACL and backend form key checks
- Guest checkout support for postcode validation
- CRUD API protected by ACL resource `PortalPeople_DisabledPostcodes::api`
- Input normalization and validation for postcodes and match type
- Public check endpoint protected with per-IP rate limiting
- Server-side checkout validation in:
  - `beforeSaveAddressInformation`
  - `beforeQuoteSubmit`

## Install (if needed)

```bash
php bin/magento module:enable PortalPeople_DisabledPostcodes
php bin/magento setup:upgrade
php bin/magento cache:clean
```
