Skip to main content

Editing Companies

This guide covers how to view and update company details, including contact information, settings, and configuration options.


Overview

What Can Be Edited?

System Admins can update most company information:

CategoryEditable FieldsNon-Editable
IdentityNameSubdomain
ContactEmail, Phone-
AddressAddress, City, Postal Code-
BrandingLogo URL-
SettingsFull-Time HoursIndustry Template
StatusIs ActiveCreated At
Why Some Fields Are Locked

Subdomain and Industry Template are locked after creation because:

  • Subdomain affects URLs and authentication routing
  • Industry Template defines roles, rooms, and terminology
  • Changing these would break existing integrations

Accessing Company Details

View Company

  1. Navigate to Admin Portal
  2. Click Companies in the sidebar
  3. Click on a company name or View button
  4. Company details are displayed

Company Details API

Endpoint: GET /api/companies/[companyId]

// Source: src/app/api/companies/[companyId]/route.ts:19-126
// Fetches company with related data
const { data } = await adminClient
.from('companies')
.select(`*,
industry_templates (*)`)
.eq('id', companyId)
.single()

// Also retrieves:
// - Staff count
// - Manager count
// - Opening hours

Response Structure

// Company details response
{
success: true,
data: {
// Identity
id: "company-uuid",
name: "Example Practice",
subdomain: "example-practice",

// Contact
email: "contact@example.com",
phone: "+44 20 7946 0958",

// Address
address: "123 High Street",
city: "London",
postalCode: "SW1A 1AA",

// Settings
industryTemplateId: "template-uuid",
fullTimeHoursPerWeek: 37.5,
logoUrl: null,
isActive: true,

// Timestamps
createdAt: "2025-01-01T00:00:00Z",
updatedAt: "2025-01-14T10:30:00Z",

// Counts
staffCount: 15,
managerCount: 2,

// Related
industryTemplate: {
id: "template-uuid",
name: "gp_practice",
displayName: "GP Practice",
terminology: { /* ... */ }
},
openingHours: { /* ... */ }
}
}

Updating Company Information

Update Company API

Endpoint: PUT /api/companies/[companyId]

// Source: src/app/api/companies/[companyId]/route.ts:128-164
export async function PUT(request: NextRequest, { params }: RouteParams) {
// Requires System Admin role
if (getAuthRole(user) !== 'SYSTEM_ADMIN') {
return ApiResponses.forbidden('Forbidden - System Admin access required')
}

const body = await request.json()
const validationResult = parseWithErrors(updateCompanySchema, body)

if (!validationResult.success) {
return ApiResponses.badRequest('Validation failed', validationResult.errors)
}

const result = await companyDB.updateCompany(
companyId,
validationResult.data
)

return ApiResponses.success(result.data, { timing: result.timing.duration })
}

Validation Schema

// Source: src/lib/validation/company.schemas.ts:97-116
export const updateCompanySchema = z.object({
name: z.string()
.min(2, 'Company name must be at least 2 characters')
.max(100, 'Company name must not exceed 100 characters')
.trim()
.optional(),
email: emailSchema.optional().nullable(),
phone: phoneSchema,
address: addressSchema,
city: citySchema,
postal_code: z.string()
.regex(postalCodeRegex, 'Invalid UK postal code format')
.optional()
.nullable(),
logo_url: z.string()
.url('Invalid logo URL')
.optional()
.nullable(),
is_active: z.boolean().optional()
})

Request Format

// Update company request
const updateCompany = async (companyId: string, updates: CompanyUpdate) => {
const response = await fetch(`/api/companies/${companyId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updates)
})

return response.json()
}

// Example usage
await updateCompany('company-uuid', {
name: 'Updated Practice Name',
email: 'newemail@practice.com',
phone: '+44 20 7946 1234',
address: '456 New Street',
city: 'Manchester',
postal_code: 'M1 1AA'
})

Editable Fields

Company Name

PropertyValue
Fieldname
TypeString
Min Length2 characters
Max Length100 characters
RequiredNo (for updates)
// Update company name
await updateCompany(companyId, {
name: 'New Practice Name'
})

Contact Information

Email

PropertyValue
Fieldemail
TypeString (email format)
Max Length255 characters
RequiredNo
// Update email
await updateCompany(companyId, {
email: 'contact@newdomain.com'
})

Phone

PropertyValue
Fieldphone
TypeString
FormatInternational phone format
Max Length30 characters
RequiredNo
// Valid phone formats
'+44 20 7946 0958'
'020 7946 0958'
'+1 555 123 4567'

Address Fields

Street Address

PropertyValue
Fieldaddress
TypeString
Max Length200 characters
RequiredNo

City

PropertyValue
Fieldcity
TypeString
Min Length2 characters
Max Length100 characters
RequiredNo

Postal Code

PropertyValue
Fieldpostal_code
TypeString
FormatUK postal code
RequiredNo
// Valid UK postal codes
'SW1A 1AA'
'M1 1AA'
'EC1A 1BB'
'W1A 0AX'

Branding

Logo URL

PropertyValue
Fieldlogo_url
TypeString (URL)
RequiredNo
// Update logo
await updateCompany(companyId, {
logo_url: 'https://example.com/logo.png'
})

Database Schema

Companies Table

// Source: src/types/database.types.ts:262-320
companies: {
Row: {
address: string | null
city: string | null
created_at: string | null
email: string | null
full_time_hours_per_week: number | null
id: string
industry_template_id: string | null
is_active: boolean | null
logo_url: string | null
name: string
phone: string | null
postal_code: string | null
subdomain: string
updated_at: string | null
}
Update: {
address?: string | null
city?: string | null
email?: string | null
full_time_hours_per_week?: number | null
is_active?: boolean | null
logo_url?: string | null
name?: string
phone?: string | null
postal_code?: string | null
}
}

Update Workflow

Step-by-Step Process

1. Navigate to company details
2. Click "Edit Company" button
3. Modify desired fields
4. Review changes
5. Click "Save Changes"
6. Confirmation displayed

UI Components

// Company edit form
const CompanyEditForm = ({ company, onSave }) => {
const [formData, setFormData] = useState({
name: company.name,
email: company.email || '',
phone: company.phone || '',
address: company.address || '',
city: company.city || '',
postal_code: company.postalCode || ''
})
const [saving, setSaving] = useState(false)

const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setSaving(true)

try {
await onSave(formData)
// Show success toast
} catch (error) {
// Show error toast
} finally {
setSaving(false)
}
}

return (
<form onSubmit={handleSubmit} className="space-y-4">
{/* Form fields */}
<button type="submit" disabled={saving}>
{saving ? 'Saving...' : 'Save Changes'}
</button>
</form>
)
}

Validation Rules

Field Validation

FieldRules
Name2-100 chars, trimmed
EmailValid email format, max 255 chars
PhoneInternational format, max 30 chars
AddressMax 200 chars
City2-100 chars
Postal CodeUK format (e.g., SW1A 1AA)
Logo URLValid URL format

Validation Patterns

// Source: src/lib/validation/company.schemas.ts:11-17
// Phone regex
const phoneRegex = /^\+?[1-9][\d\s\-().]{0,20}$/

// Postal code regex (UK format)
const postalCodeRegex = /^[A-Z]{1,2}\d[A-Z\d]?\s?\d[A-Z]{2}$/i

Error Handling

// Validation error response
{
success: false,
error: "Validation failed",
details: {
name: ["Company name must be at least 2 characters"],
postal_code: ["Invalid UK postal code format"],
email: ["Invalid email format"]
}
}

Best Practices

Do's and Don'ts

DoDon't
Verify changes before savingMake changes without review
Keep contact info currentLeave outdated information
Use official company emailUse personal email addresses
Maintain accurate addressSkip address updates
Upload proper logo formatUse low-quality images

Update Considerations

  1. Notify Company Manager - Inform of significant changes
  2. Verify Contact Details - Ensure accuracy of updates
  3. Update Consistently - Keep all records synchronised
  4. Document Changes - Note reason for updates

Audit Trail

Change Logging

All company updates are logged:

// Activity log entry
{
action: 'company_updated',
company_id: 'company-uuid',
manager_id: 'system-admin-uuid',
details: {
fields_updated: ['name', 'email'],
old_values: { name: 'Old Name', email: 'old@email.com' },
new_values: { name: 'New Name', email: 'new@email.com' }
},
created_at: '2025-01-14T10:30:00Z',
ip_address: '192.168.1.1'
}

Troubleshooting

Common Issues

IssueCauseSolution
Validation failedInvalid field formatCheck field requirements
Update failedNetwork errorRetry the operation
Forbidden errorInsufficient permissionsVerify System Admin role
Company not foundInvalid company IDCheck company exists

Error Messages

ErrorMeaningAction
"Company name must be at least 2 characters"Name too shortUse longer name
"Invalid UK postal code format"Wrong postcodeUse format like SW1A 1AA
"Invalid email format"Bad emailCheck email syntax
"Forbidden - System Admin access required"Not authorisedLogin as System Admin


Source Files:

  • src/app/api/companies/[companyId]/route.ts - Company API endpoint
  • src/lib/validation/company.schemas.ts - Validation schemas
  • src/lib/db/company.ts - Database operations
  • src/types/database.types.ts - Database type definitions