- DoctorClaimController: ALTCHA CaptchaGuard on /claim (dev no-op via
ALTCHA_ENABLED=false); optional `mobile` field must match the logged-in
user's number (422 ERR_CONFLICT_001 on mismatch)
- DoctorController::delete: now IS_AUTHENTICATED_FULLY — admin (any) or the
owner of a claimed profile (IDOR-guarded); FK appointment guard kept
- DoctorDetailPage address map: MapController calls map.invalidateSize()
before flyTo (fixes needing to pick a city twice on a freshly-mounted map);
geocode retries once (nominatim empty/429 on first hit)
- tests: mobile mismatch, owner-delete allowed + others 403, unclaimed not
deletable by random user
- docs: doctor-claim.md (mobile+captcha), doctor.md (delete permission)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Root cause of "دکتر دکتر …" (and ellipsis-truncated "…نی") in admin: IRIMC
names already contain the «دکتر» title, while the panel renders «دکتر {name}».
Convention is to store the bare name.
- DoctorImportService: normalize name via PersianText::stripDoctorTitle
(also fixes ي/ی, ك/ک, half-space)
- PersianText::stripDoctorTitle now strips consecutive «دکتر دکتر …» prefixes
- app:doctors:fix-irimc-names: one-off backfill for existing source='irimc'
rows (dry-run supported) — fixed 340 rows
- app:doctors:purge: FK-safe full wipe of doctors + all dependent tables +
orphan surrogate users, for a clean test DB (dry-run default, --force to
apply, prod-guarded)
- tests: PersianTextTest cases for the title stripping; DoctorImportTest
asserts stored name has no «دکتر» prefix
- docs/api/doctor-import.md: name convention + the two new commands
Verified: import "دکتر صفورا حجازی نیا" → stored "صفورا حجازی نیا" → panel
shows single «دکتر صفورا حجازی نیا».
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Implemented ClinicInvitationWebController to manage the invitation process via web.
- Added view and respond methods to handle invitation display and responses.
- Created result.html.twig and view.html.twig templates for rendering invitation results and views.
- Integrated CSRF protection for form submissions.
- Established routes for invitation viewing and responding.
- Introduced new columns: owner_status, source, source_ref, managed_by, and claimed_at to the doctors table.
- Created indexes for owner_status and source to optimize queries related to unclaimed doctors.
feat(auth): implement SystemOwnerCommand for managing system-owner user
- Added command to create, activate, and deactivate a system-owner user for IRIMC crawler.
- Ensured the user has ROLE_ADMIN to access import endpoints.
- Handled password setting and user status management within the command.
- Created JSON representation of AltchaService class and its methods, including imports and relationships.
- Added documentation for the Captcha API, detailing endpoints and responses.
- Introduced test cases for AltchaService, covering various functionalities and edge cases.
- Introduced a new endpoint `/api/v1/altcha/config` in CaptchaController to return the status of the ALTCHA captcha.
- Updated HomeController to inject AltchaService and pass the captcha status to the home page template.
- Modified the home.html.twig template to conditionally render the ALTCHA widget based on the captcha status.
- Updated manifest.json and cache files to reflect changes in the codebase.
- Added CaptchaGuard dependency to PasswordAuthenticator.
- Implemented Captcha validation in the authenticate method to enhance security.
- Updated the login modal in home.html.twig to redirect to the admin panel instead of opening a modal.
- Enhanced the Altcha widget with localized strings for better user experience.
- Removed the login modal implementation from home.html.twig to streamline the login process.
- Updated manifest.json and AST cache files to reflect changes in the codebase.
- Added AltchaService class for managing ALTCHA captcha challenges and solutions.
- Created CaptchaController to handle API requests for generating challenges.
- Introduced CaptchaGuard for validating captcha solutions on public endpoints.
- Developed unit tests for AltchaService to ensure challenge creation and solution verification functionality.
- Implemented integration tests for the Captcha API endpoint and captcha bypass behavior when disabled.
- Added documentation for the Captcha API in the corresponding markdown file.
- Created migration to add representation_cities table and domain, is_global fields to representations.
- Implemented SiteContextController to resolve domain to site context (city | representation | unknown).
- Developed DomainContext and DomainContextResolver services for domain mapping.
- Added tests for DomainContextResolver and commission logic based on domain ownership.
- Created a new JSON file for the City entity's AST representation, detailing its methods and properties.
- Added a migration to alter the cities table by adding a nullable title column.
- Created a new AST JSON file for SmsServiceLookupOnlyTest.php, detailing nodes, edges, and raw calls for better code analysis.
- Added a new migration (Version20260707202553) to alter the sms_logs table by adding a nullable template_code column.
- Removed SmsTextResolver dependency from multiple services and controllers.
- Introduced dispatchTemplate method in SmsService to handle SMS sending with templates.
- Updated existing SMS sending logic across various services (OtpService, PreRegistrationController, ClinicInvitationService, PaymentManager, SecretaryController, RepresentationActionController) to utilize the new dispatchTemplate method.
- Enhanced SmsMessageTemplate entity to include kavenegar_template and token_map fields.
- Created migration to add new fields to the sms_message_templates table and populate them with existing data.
- Updated SeedSmsMessageTemplatesCommand to handle new template structure.
- Added documentation for the new SMS template structure and usage.
- Added support for sending OTP messages using Kavenegar's VerifyLookup method, ensuring compliance with specified token formatting and template usage.
- Updated OtpService to handle new template parameters and fallback mechanisms.
- Introduced ImageCropModal component for cropping images with a user-friendly interface.
- Created utility function for cropping images and generating downloadable files.
Mellat/SEP return the result via a user-browser redirect (POST/GET), so the
received IP is the user's, not Shaparak's. The IP allowlist therefore rejected
every real callback — including user cancel — with 'forbidden'. Security is
provided by the tamper check (RefId/SaleOrderId) and server-side verify.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Implemented `refund` and `reverse` methods in `PaymentGatewayInterface`.
- Added `PaymentRefundResult` class to handle refund operation results.
- Enhanced `MockGateway` and `SepGateway` to support refund and reversal operations.
- Updated `PaymentManager` to include `refundPayment` and `reversePayment` methods for handling refunds and reversals in transactions.
- Modified `ClinicSubscriptionRepository` and `SubscriptionService` to manage subscriptions during refunds.
- Added admin API endpoints for processing refunds and reversals.
- Updated security headers to allow form actions to the sandbox environment.
- Documented the new refund and reversal features in the API documentation.
- Refactor PaymentController to delegate payment processing to PaymentManager.
- Add findByOrderIdForUpdate method in PaymentRepository for pessimistic locking.
- Create PaymentLog entity and repository for auditing payment actions.
- Implement startGatewayHandoff and processCallback methods in PaymentManager.
- Introduce transaction handling and logging for payment verification.
- Update payment flow to ensure idempotency and prevent race conditions.
- Enhance security by logging sensitive actions without exposing credentials.
- Update database schema with migration for payment_logs table.
- Document changes in payment flow architecture.
feat(appointment): enhance appointment detail page with time formatting and additional info
fix(payment): update payment query to fetch from the correct endpoint and adjust response structure
docs(api): add search parameter to payments API documentation and detail response structure
test(payment): add unit test for MellatGateway to verify null credentials handling
- Introduced SmokeEndpointsCommand to send HTTP requests to all /api and /oauth endpoints on the live site, ensuring logs are generated in the app_log table.
- Implemented non-destructive testing by using real IDs for GET requests and non-existent IDs for write operations.
- Added functionality to authenticate as an admin using a fixed OTP for development.
- Created tests for endpoint sweeps to verify that no 5xx errors occur during various conditions, including no-auth and wrong-role scenarios.
- Established RouteManifest for public success paths that should return 200 without requiring fixtures.
- Add LogPruneService to handle the deletion of old logs based on retention settings.
- Create PruneLogsCommand to provide a console command for log pruning.
- Introduce PruneLogsMessage and PruneLogsHandler for message handling related to log pruning.
- Update the AST cache with new classes and their relationships.
- Created new AST JSON file for the doctor service API documentation, detailing endpoints, parameters, and responses.
- Added AST JSON file for the TagController, including methods and their relationships with imported classes.
- Introduced AST JSON file for the SmsLog entity, outlining its methods and dependencies.
- Implemented CategoryImporter service to handle bulk export/import logic for categories.
- Created SeedCategoriesCommand to seed category tables from JSON files in data/seed/.
- Added validation and normalization for category data during import.
- Ensured proper error handling and user feedback during the seeding process.
- Implemented export functionality to retrieve all rows from specified category tables.
- Developed import functionality with strict validation and referential integrity checks.
- Added error handling for various import scenarios including invalid formats and duplicate entries.
- Introduced tests for import functionality to ensure correct behavior and validation.
- Created migration to set up app_log table for storing application logs.
- Added AppLog entity and repository for ORM handling of logs.
- Developed DbLogger service to persist logs of level WARNING and above to the database while maintaining existing logging behavior.
- Implemented tests for admin log retrieval and DbLogger functionality to ensure proper logging behavior.
- Enhanced logging context sanitization for better error tracking.
- M10 GET /settlement: was unbounded; add page/limit + countByUser + data.meta.
- M11 GET /admin/comments/pending: paginate findPending + countPending.
- M12 GET /comments/{doctor}: paginate the fetch-joined roots query via
Paginator(fetchJoinCollection) + countApprovedRootsByDoctor.
All keep the existing { data: { data: [...] } } envelope and add data.meta
(backward compatible). Default limit 50 / max 100.
Regressions: SettlementListPaginationTest, CommentPaginationTest (both fail
without the limits). Also de-flaked SendCodeMobileRateLimitTest (randomised the
IP block so the persistent per-IP limiter buckets don't accumulate across runs).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>