# Story 2.2: Company/Corporate Client Account Management ## Epic Reference **Epic 2:** User Management System ## User Story As an **admin**, I want **to create, view, edit, and manage company/corporate client accounts**, So that **I can serve corporate clients with their unique data requirements**. ## Story Context ### Existing System Integration - **Integrates with:** `users` table (company-specific fields), `admin_logs` table - **Technology:** Livewire Volt (class-based), Flux UI forms, Pest tests - **Follows pattern:** Same CRUD pattern as Story 2.1 Individual Clients - **Key Files to Create/Modify:** - `resources/views/livewire/admin/users/company/` - Volt components (index, create, edit, show) - `app/Models/User.php` - Add `scopeCompany()` method - `resources/lang/ar/messages.php` - Arabic translations - `resources/lang/en/messages.php` - English translations - `tests/Feature/Admin/CompanyClientTest.php` - Feature tests ## Acceptance Criteria ### Create Company Client - [ ] Form with required fields: - Company Name (required) - Company Registration Number (required, unique) - Contact Person Name (required) - Contact Person ID (required) - Email Address (required, unique) - Phone Number (required) - Password (admin-set, required) - Preferred Language (Arabic/English dropdown) - [ ] Validation for all required fields - [ ] Duplicate email/registration number prevention - [ ] Success message on creation ### Multiple Contact Persons (OUT OF SCOPE) > **Note:** Multiple contact persons support is deferred to a future enhancement story. This story implements single contact person stored directly on the `users` table. The `contact_persons` table migration in Technical Notes is for reference only if this feature is later prioritized. ### List View - [ ] Display all company clients (user_type = 'company') - [ ] Columns: Company Name, Contact Person, Email, Reg #, Status, Created Date - [ ] Pagination (10/25/50 per page) - [ ] Default sort by created date ### Search & Filter - [ ] Search by company name, email, or registration number - [ ] Filter by status (active/deactivated/all) - [ ] Real-time search with debounce ### Edit Company - [ ] Edit all company information - [ ] Update contact person details - [ ] Validation same as create - [ ] Success message on update ### View Company Profile - [ ] Display all company information (including contact person details) - [ ] Show consultation history summary - [ ] Show timeline history summary ### Quality Requirements - [ ] Bilingual form labels and messages - [ ] Proper form validation - [ ] Audit log entries for all operations - [ ] Tests for CRUD operations ## Technical Notes ### User Model Scope ```php public function scopeCompany($query) { return $query->where('user_type', 'company'); } ``` ### Database Fields for Company ``` users table: - company_name (nullable, required for company type) - company_registration (nullable, unique when not null) - contact_person_name (nullable, required for company) - contact_person_id (nullable, required for company) ``` ### Future Reference: Separate Contact Persons Table > **Note:** This migration is NOT part of this story. It is preserved here for future reference if multiple contact persons feature is prioritized. ```php // contact_persons migration (FUTURE - NOT IN SCOPE) Schema::create('contact_persons', function (Blueprint $table) { $table->id(); $table->foreignId('user_id')->constrained()->cascadeOnDelete(); $table->string('name'); $table->string('national_id'); $table->string('phone')->nullable(); $table->string('email')->nullable(); $table->boolean('is_primary')->default(false); $table->timestamps(); }); ``` ### Validation Rules ```php public function rules(): array { return [ 'company_name' => ['required', 'string', 'max:255'], 'company_registration' => ['required', 'string', 'unique:users,company_registration'], 'contact_person_name' => ['required', 'string', 'max:255'], 'contact_person_id' => ['required', 'string'], 'email' => ['required', 'email', 'unique:users,email'], 'phone' => ['required', 'string'], 'password' => ['required', 'string', 'min:8'], 'preferred_language' => ['required', 'in:ar,en'], ]; } ``` ### Volt Component for Create Follow the same component structure as Story 2.1 (`docs/stories/story-2.1-individual-client-account-management.md`). ```php validate(); $user = User::create([ ...$validated, 'user_type' => 'company', 'name' => $this->company_name, // For display purposes 'password' => Hash::make($this->password), 'status' => 'active', ]); // Log action (same pattern as Story 2.1) AdminLog::create([ 'admin_id' => auth()->id(), 'action_type' => 'create', 'target_type' => 'user', 'target_id' => $user->id, 'new_values' => $user->only(['company_name', 'email', 'company_registration']), 'ip_address' => request()->ip(), ]); // Send welcome email (depends on Story 2.5) session()->flash('success', __('messages.company_created')); $this->redirect(route('admin.users.index')); } }; ``` ## Testing Requirements ### Test Approach - Feature tests using Pest with `Volt::test()` for Livewire components - Factory-based test data generation ### Key Test Scenarios #### Create Company Client - [ ] Successfully create company with all valid required fields - [ ] Validation fails when required fields are missing - [ ] Validation fails for duplicate email address - [ ] Validation fails for duplicate company registration number - [ ] Preferred language defaults to Arabic when not specified - [ ] Audit log entry created on successful creation #### List View - [ ] List displays only company type users (excludes individual/admin) - [ ] Pagination works correctly (10/25/50 per page) - [ ] Default sort is by created date descending #### Search & Filter - [ ] Search by company name returns correct results - [ ] Search by email returns correct results - [ ] Search by registration number returns correct results - [ ] Filter by active status works - [ ] Filter by deactivated status works - [ ] Combined search and filter works correctly #### Edit Company - [ ] Successfully update company information - [ ] Validation fails for duplicate email (excluding current record) - [ ] Validation fails for duplicate registration number (excluding current record) - [ ] Audit log entry created on successful update #### View Profile - [ ] Profile displays all company information correctly - [ ] Consultation history summary displays (empty state if none) - [ ] Timeline history summary displays (empty state if none) #### Bilingual Support - [ ] Form labels display correctly in Arabic - [ ] Form labels display correctly in English - [ ] Validation messages display in user's preferred language ## Definition of Done - [ ] Create company client form works - [ ] List view displays all company clients - [ ] Search and filter functional - [ ] Edit company works with validation - [ ] View profile shows complete information - [ ] Duplicate prevention works - [ ] Audit logging implemented - [ ] Bilingual support complete - [ ] Tests pass for all CRUD operations - [ ] Code formatted with Pint ## Dependencies - **Epic 1:** Authentication system, database schema - **Story 1.1:** Database schema must include the following columns in `users` table: - `user_type` (enum: 'individual', 'company', 'admin') - `status` (enum: 'active', 'deactivated') - `phone` (string) - `preferred_language` (enum: 'ar', 'en') - `company_name` (nullable string) - `company_registration` (nullable string, unique when not null) - `contact_person_name` (nullable string) - `contact_person_id` (nullable string) - `national_id` (nullable string, unique when not null) - **Story 2.1:** CRUD patterns established in `docs/stories/story-2.1-individual-client-account-management.md` ## Risk Assessment - **Primary Risk:** Complex contact persons relationship - **Mitigation:** Start simple (single contact), enhance later if needed - **Rollback:** Use simple fields on users table ## Estimation **Complexity:** Medium **Estimated Effort:** 4-5 hours