- 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>
135 lines
3.6 KiB
TypeScript
135 lines
3.6 KiB
TypeScript
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
|
|
}
|
|
}
|