Production deployment with Docker and full system fixes

- Added Docker support (Dockerfiles, docker-compose.yml)
- Fixed authentication and authorization (token storage, CORS, permissions)
- Fixed API response transformations for all modules
- Added production deployment scripts and guides
- Fixed frontend permission checks and module access
- Added database seeding script for production
- Complete documentation for deployment and configuration

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Talal Sharabi
2026-02-11 11:25:20 +04:00
parent 35daa52767
commit f31d71ff5a
52 changed files with 9359 additions and 1578 deletions

View File

@@ -0,0 +1,134 @@
import { api } from '../api'
export interface Deal {
id: string
dealNumber: string
name: string
contactId: string
contact?: any
structure: string // B2B, B2C, B2G, PARTNERSHIP
pipelineId: string
pipeline?: any
stage: string
estimatedValue: number
actualValue?: number
currency: string
probability?: number
expectedCloseDate?: string
actualCloseDate?: string
ownerId: string
owner?: any
wonReason?: string
lostReason?: string
fiscalYear: number
status: string
createdAt: string
updatedAt: string
}
export interface CreateDealData {
name: string
contactId: string
structure: string
pipelineId: string
stage: string
estimatedValue: number
probability?: number
expectedCloseDate?: string
ownerId?: string
fiscalYear?: number
}
export interface UpdateDealData extends Partial<CreateDealData> {
actualValue?: number
actualCloseDate?: string
wonReason?: string
lostReason?: string
status?: string
}
export interface DealFilters {
search?: string
structure?: string
stage?: string
status?: string
ownerId?: string
fiscalYear?: number
page?: number
pageSize?: number
}
export interface DealsResponse {
deals: Deal[]
total: number
page: number
pageSize: number
totalPages: number
}
export const dealsAPI = {
// Get all deals with filters and pagination
getAll: async (filters: DealFilters = {}): Promise<DealsResponse> => {
const params = new URLSearchParams()
if (filters.search) params.append('search', filters.search)
if (filters.structure) params.append('structure', filters.structure)
if (filters.stage) params.append('stage', filters.stage)
if (filters.status) params.append('status', filters.status)
if (filters.ownerId) params.append('ownerId', filters.ownerId)
if (filters.fiscalYear) params.append('fiscalYear', filters.fiscalYear.toString())
if (filters.page) params.append('page', filters.page.toString())
if (filters.pageSize) params.append('pageSize', filters.pageSize.toString())
const response = await api.get(`/crm/deals?${params.toString()}`)
const { data, pagination } = response.data
return {
deals: data || [],
total: pagination?.total || 0,
page: pagination?.page || 1,
pageSize: pagination?.pageSize || 20,
totalPages: pagination?.totalPages || 0,
}
},
// Get single deal by ID
getById: async (id: string): Promise<Deal> => {
const response = await api.get(`/crm/deals/${id}`)
return response.data.data
},
// Create new deal
create: async (data: CreateDealData): Promise<Deal> => {
const response = await api.post('/crm/deals', data)
return response.data.data
},
// Update existing deal
update: async (id: string, data: UpdateDealData): Promise<Deal> => {
const response = await api.put(`/crm/deals/${id}`, data)
return response.data.data
},
// Update deal stage
updateStage: async (id: string, stage: string): Promise<Deal> => {
const response = await api.patch(`/crm/deals/${id}/stage`, { stage })
return response.data.data
},
// Mark deal as won
win: async (id: string, actualValue: number, wonReason: string): Promise<Deal> => {
const response = await api.post(`/crm/deals/${id}/win`, { actualValue, wonReason })
return response.data.data
},
// Mark deal as lost
lose: async (id: string, lostReason: string): Promise<Deal> => {
const response = await api.post(`/crm/deals/${id}/lose`, { lostReason })
return response.data.data
},
// Get deal history
getHistory: async (id: string): Promise<any[]> => {
const response = await api.get(`/crm/deals/${id}/history`)
return response.data.data
}
}