@hed-hog/operations 0.0.347 → 0.0.349
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/controllers/operations-contracts.controller.d.ts +9 -9
- package/dist/operations.service.js +30 -30
- package/hedhog/frontend/app/_components/project-details-screen.tsx.ejs +5 -5
- package/hedhog/frontend/app/_components/project-form-screen.tsx.ejs +39 -39
- package/package.json +5 -5
- package/src/operations.service.ts +33 -33
|
@@ -25,7 +25,7 @@ export declare class OperationsContractsController {
|
|
|
25
25
|
contractCategory: "other" | "client" | "internal" | "employee" | "contractor" | "supplier" | "vendor" | "partner";
|
|
26
26
|
contractType: "other" | "clt" | "pj" | "freelancer_agreement" | "service_agreement" | "fixed_term" | "recurring_service" | "nda" | "amendment" | "addendum";
|
|
27
27
|
clientName: string | null;
|
|
28
|
-
signatureStatus: "pending" | "
|
|
28
|
+
signatureStatus: "pending" | "not_started" | "partially_signed" | "signed" | "expired";
|
|
29
29
|
isActive: boolean;
|
|
30
30
|
billingModel: "time_and_material" | "monthly_retainer" | "fixed_price";
|
|
31
31
|
accountManagerCollaboratorId: number | null;
|
|
@@ -38,7 +38,7 @@ export declare class OperationsContractsController {
|
|
|
38
38
|
effectiveDate: string | null;
|
|
39
39
|
budgetAmount: number | null;
|
|
40
40
|
monthlyHourCap: number | null;
|
|
41
|
-
status: "active" | "closed" | "draft" | "
|
|
41
|
+
status: "active" | "closed" | "draft" | "archived" | "expired" | "under_review" | "renewal";
|
|
42
42
|
creationMode: ("template" | "blank" | "upload" | "duplicate") | null;
|
|
43
43
|
wizardStep: number | null;
|
|
44
44
|
description: string | null;
|
|
@@ -77,7 +77,7 @@ export declare class OperationsContractsController {
|
|
|
77
77
|
mimeType: string;
|
|
78
78
|
fileContentBase64: string | null;
|
|
79
79
|
isCurrent: boolean;
|
|
80
|
-
extractionStatus: ("pending" | "
|
|
80
|
+
extractionStatus: ("pending" | "completed" | "failed" | "skipped" | "processing") | null;
|
|
81
81
|
extractionSummary: string | null;
|
|
82
82
|
notes: string | null;
|
|
83
83
|
createdAt: string;
|
|
@@ -98,7 +98,7 @@ export declare class OperationsContractsController {
|
|
|
98
98
|
contractCategory: "other" | "client" | "internal" | "employee" | "contractor" | "supplier" | "vendor" | "partner";
|
|
99
99
|
contractType: "other" | "clt" | "pj" | "freelancer_agreement" | "service_agreement" | "fixed_term" | "recurring_service" | "nda" | "amendment" | "addendum";
|
|
100
100
|
clientName: string | null;
|
|
101
|
-
signatureStatus: "pending" | "
|
|
101
|
+
signatureStatus: "pending" | "not_started" | "partially_signed" | "signed" | "expired";
|
|
102
102
|
isActive: boolean;
|
|
103
103
|
billingModel: "time_and_material" | "monthly_retainer" | "fixed_price";
|
|
104
104
|
accountManagerCollaboratorId: number | null;
|
|
@@ -111,7 +111,7 @@ export declare class OperationsContractsController {
|
|
|
111
111
|
effectiveDate: string | null;
|
|
112
112
|
budgetAmount: number | null;
|
|
113
113
|
monthlyHourCap: number | null;
|
|
114
|
-
status: "active" | "closed" | "draft" | "
|
|
114
|
+
status: "active" | "closed" | "draft" | "archived" | "expired" | "under_review" | "renewal";
|
|
115
115
|
creationMode: ("template" | "blank" | "upload" | "duplicate") | null;
|
|
116
116
|
wizardStep: number | null;
|
|
117
117
|
description: string | null;
|
|
@@ -150,7 +150,7 @@ export declare class OperationsContractsController {
|
|
|
150
150
|
mimeType: string;
|
|
151
151
|
fileContentBase64: string | null;
|
|
152
152
|
isCurrent: boolean;
|
|
153
|
-
extractionStatus: ("pending" | "
|
|
153
|
+
extractionStatus: ("pending" | "completed" | "failed" | "skipped" | "processing") | null;
|
|
154
154
|
extractionSummary: string | null;
|
|
155
155
|
notes: string | null;
|
|
156
156
|
createdAt: string;
|
|
@@ -171,7 +171,7 @@ export declare class OperationsContractsController {
|
|
|
171
171
|
contractCategory: "other" | "client" | "internal" | "employee" | "contractor" | "supplier" | "vendor" | "partner";
|
|
172
172
|
contractType: "other" | "clt" | "pj" | "freelancer_agreement" | "service_agreement" | "fixed_term" | "recurring_service" | "nda" | "amendment" | "addendum";
|
|
173
173
|
clientName: string | null;
|
|
174
|
-
signatureStatus: "pending" | "
|
|
174
|
+
signatureStatus: "pending" | "not_started" | "partially_signed" | "signed" | "expired";
|
|
175
175
|
isActive: boolean;
|
|
176
176
|
billingModel: "time_and_material" | "monthly_retainer" | "fixed_price";
|
|
177
177
|
accountManagerCollaboratorId: number | null;
|
|
@@ -184,7 +184,7 @@ export declare class OperationsContractsController {
|
|
|
184
184
|
effectiveDate: string | null;
|
|
185
185
|
budgetAmount: number | null;
|
|
186
186
|
monthlyHourCap: number | null;
|
|
187
|
-
status: "active" | "closed" | "draft" | "
|
|
187
|
+
status: "active" | "closed" | "draft" | "archived" | "expired" | "under_review" | "renewal";
|
|
188
188
|
creationMode: ("template" | "blank" | "upload" | "duplicate") | null;
|
|
189
189
|
wizardStep: number | null;
|
|
190
190
|
description: string | null;
|
|
@@ -223,7 +223,7 @@ export declare class OperationsContractsController {
|
|
|
223
223
|
mimeType: string;
|
|
224
224
|
fileContentBase64: string | null;
|
|
225
225
|
isCurrent: boolean;
|
|
226
|
-
extractionStatus: ("pending" | "
|
|
226
|
+
extractionStatus: ("pending" | "completed" | "failed" | "skipped" | "processing") | null;
|
|
227
227
|
extractionSummary: string | null;
|
|
228
228
|
notes: string | null;
|
|
229
229
|
createdAt: string;
|
|
@@ -1938,21 +1938,21 @@ let OperationsService = OperationsService_1 = class OperationsService {
|
|
|
1938
1938
|
COUNT(DISTINCT pa.id)::int AS "teamSize"
|
|
1939
1939
|
FROM operations_project p
|
|
1940
1940
|
LEFT JOIN operations_contract c ON c.id = p.contract_id
|
|
1941
|
-
LEFT JOIN operations_collaborator m ON m.id = p.manager_collaborator_id
|
|
1942
|
-
LEFT JOIN person cp ON cp.id = p.client_person_id
|
|
1943
|
-
LEFT JOIN person mp ON mp.id = m.person_id
|
|
1944
|
-
LEFT JOIN LATERAL (
|
|
1945
|
-
SELECT u.photo_id
|
|
1946
|
-
FROM person_user pu
|
|
1947
|
-
JOIN "user" u ON u.id = pu.user_id
|
|
1948
|
-
WHERE pu.person_id = p.client_person_id
|
|
1949
|
-
ORDER BY pu.id ASC
|
|
1950
|
-
LIMIT 1
|
|
1951
|
-
) client_user ON TRUE
|
|
1952
|
-
LEFT JOIN operations_project_assignment pa
|
|
1953
|
-
ON pa.project_id = p.id
|
|
1954
|
-
AND pa.deleted_at IS NULL
|
|
1955
|
-
AND pa.status IN ('planned', 'active')
|
|
1941
|
+
LEFT JOIN operations_collaborator m ON m.id = p.manager_collaborator_id
|
|
1942
|
+
LEFT JOIN person cp ON cp.id = p.client_person_id
|
|
1943
|
+
LEFT JOIN person mp ON mp.id = m.person_id
|
|
1944
|
+
LEFT JOIN LATERAL (
|
|
1945
|
+
SELECT u.photo_id
|
|
1946
|
+
FROM person_user pu
|
|
1947
|
+
JOIN "user" u ON u.id = pu.user_id
|
|
1948
|
+
WHERE pu.person_id = p.client_person_id
|
|
1949
|
+
ORDER BY pu.id ASC
|
|
1950
|
+
LIMIT 1
|
|
1951
|
+
) client_user ON TRUE
|
|
1952
|
+
LEFT JOIN operations_project_assignment pa
|
|
1953
|
+
ON pa.project_id = p.id
|
|
1954
|
+
AND pa.deleted_at IS NULL
|
|
1955
|
+
AND pa.status IN ('planned', 'active')
|
|
1956
1956
|
WHERE ${whereClause}
|
|
1957
1957
|
GROUP BY p.id, c.id, m.id, cp.id, mp.id, client_user.photo_id`;
|
|
1958
1958
|
if (!pagination) {
|
|
@@ -5408,21 +5408,21 @@ let OperationsService = OperationsService_1 = class OperationsService {
|
|
|
5408
5408
|
MAX(CASE WHEN pa.collaborator_id = $2 THEN pa.id END)::int AS "myAssignmentId",
|
|
5409
5409
|
MAX(CASE WHEN pa.collaborator_id = $2 THEN COALESCE(project_role_locale.name, pa.role_label) END) AS "myRoleLabel",
|
|
5410
5410
|
COUNT(DISTINCT pa.id)::int AS "teamSize"
|
|
5411
|
-
FROM operations_project p
|
|
5412
|
-
LEFT JOIN operations_contract c ON c.id = p.contract_id
|
|
5413
|
-
LEFT JOIN operations_collaborator m ON m.id = p.manager_collaborator_id
|
|
5414
|
-
LEFT JOIN person client_person ON client_person.id = p.client_person_id
|
|
5415
|
-
LEFT JOIN LATERAL (
|
|
5416
|
-
SELECT u.photo_id
|
|
5417
|
-
FROM person_user pu
|
|
5418
|
-
JOIN "user" u ON u.id = pu.user_id
|
|
5419
|
-
WHERE pu.person_id = p.client_person_id
|
|
5420
|
-
ORDER BY pu.id ASC
|
|
5421
|
-
LIMIT 1
|
|
5422
|
-
) client_user ON TRUE
|
|
5423
|
-
LEFT JOIN operations_project_assignment pa
|
|
5424
|
-
ON pa.project_id = p.id
|
|
5425
|
-
AND pa.deleted_at IS NULL
|
|
5411
|
+
FROM operations_project p
|
|
5412
|
+
LEFT JOIN operations_contract c ON c.id = p.contract_id
|
|
5413
|
+
LEFT JOIN operations_collaborator m ON m.id = p.manager_collaborator_id
|
|
5414
|
+
LEFT JOIN person client_person ON client_person.id = p.client_person_id
|
|
5415
|
+
LEFT JOIN LATERAL (
|
|
5416
|
+
SELECT u.photo_id
|
|
5417
|
+
FROM person_user pu
|
|
5418
|
+
JOIN "user" u ON u.id = pu.user_id
|
|
5419
|
+
WHERE pu.person_id = p.client_person_id
|
|
5420
|
+
ORDER BY pu.id ASC
|
|
5421
|
+
LIMIT 1
|
|
5422
|
+
) client_user ON TRUE
|
|
5423
|
+
LEFT JOIN operations_project_assignment pa
|
|
5424
|
+
ON pa.project_id = p.id
|
|
5425
|
+
AND pa.deleted_at IS NULL
|
|
5426
5426
|
LEFT JOIN operations_project_role project_role
|
|
5427
5427
|
ON project_role.id = pa.project_role_id
|
|
5428
5428
|
AND project_role.deleted_at IS NULL
|
|
@@ -2519,11 +2519,11 @@ export function ProjectDetailsScreen({ projectId }: { projectId: number }) {
|
|
|
2519
2519
|
<div className="flex cursor-default items-center gap-2 border-r px-3 py-2 transition hover:bg-muted/30">
|
|
2520
2520
|
<Gauge className="size-3.5 shrink-0 text-muted-foreground" />
|
|
2521
2521
|
<div className="flex items-center gap-1.5">
|
|
2522
|
-
<div className="h-1.5 w-20 overflow-hidden rounded-full bg-muted">
|
|
2523
|
-
<motion.div
|
|
2524
|
-
animate={{ width: `${displayedProgress}%` }}
|
|
2525
|
-
transition={{ duration: 0.7, ease: 'easeOut' }}
|
|
2526
|
-
className="h-full rounded-full bg-primary"
|
|
2522
|
+
<div className="h-1.5 w-20 overflow-hidden rounded-full bg-muted">
|
|
2523
|
+
<motion.div
|
|
2524
|
+
animate={{ width: `${displayedProgress}%` }}
|
|
2525
|
+
transition={{ duration: 0.7, ease: 'easeOut' }}
|
|
2526
|
+
className="h-full rounded-full bg-primary"
|
|
2527
2527
|
/>
|
|
2528
2528
|
</div>
|
|
2529
2529
|
<span className="w-8 text-right font-semibold tabular-nums">
|
|
@@ -159,33 +159,33 @@ type ProjectFormState = {
|
|
|
159
159
|
teamAssignments: TeamAssignmentState[];
|
|
160
160
|
};
|
|
161
161
|
|
|
162
|
-
type ProjectFormValues = ProjectFormState;
|
|
163
|
-
|
|
164
|
-
type ManagerOption = {
|
|
165
|
-
id: number;
|
|
166
|
-
title: string;
|
|
167
|
-
description: string;
|
|
168
|
-
avatarUrl: string | null;
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
function toManagerOption(collaborator: OperationsCollaborator): ManagerOption {
|
|
172
|
-
return {
|
|
173
|
-
id: collaborator.id,
|
|
174
|
-
title: collaborator.displayName,
|
|
175
|
-
description: [collaborator.department, collaborator.title]
|
|
176
|
-
.filter(Boolean)
|
|
177
|
-
.join(' • '),
|
|
178
|
-
avatarUrl:
|
|
179
|
-
getUserPhotoUrl(collaborator.userPhotoId) ??
|
|
180
|
-
getPersonAvatarUrl(collaborator.personAvatarId) ??
|
|
181
|
-
null,
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function generateProjectCode(name: string): string {
|
|
186
|
-
const words = name.trim().split(/\s+/).filter(Boolean);
|
|
187
|
-
if (words.length === 0) return '';
|
|
188
|
-
if (words.length === 1) return words[0]!.slice(0, 5).toUpperCase();
|
|
162
|
+
type ProjectFormValues = ProjectFormState;
|
|
163
|
+
|
|
164
|
+
type ManagerOption = {
|
|
165
|
+
id: number;
|
|
166
|
+
title: string;
|
|
167
|
+
description: string;
|
|
168
|
+
avatarUrl: string | null;
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
function toManagerOption(collaborator: OperationsCollaborator): ManagerOption {
|
|
172
|
+
return {
|
|
173
|
+
id: collaborator.id,
|
|
174
|
+
title: collaborator.displayName,
|
|
175
|
+
description: [collaborator.department, collaborator.title]
|
|
176
|
+
.filter(Boolean)
|
|
177
|
+
.join(' • '),
|
|
178
|
+
avatarUrl:
|
|
179
|
+
getUserPhotoUrl(collaborator.userPhotoId) ??
|
|
180
|
+
getPersonAvatarUrl(collaborator.personAvatarId) ??
|
|
181
|
+
null,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function generateProjectCode(name: string): string {
|
|
186
|
+
const words = name.trim().split(/\s+/).filter(Boolean);
|
|
187
|
+
if (words.length === 0) return '';
|
|
188
|
+
if (words.length === 1) return words[0]!.slice(0, 5).toUpperCase();
|
|
189
189
|
return words
|
|
190
190
|
.map((w) => w[0]!.toUpperCase())
|
|
191
191
|
.join('')
|
|
@@ -791,9 +791,9 @@ export function ProjectFormScreen({
|
|
|
791
791
|
[rawCollaborators]
|
|
792
792
|
);
|
|
793
793
|
|
|
794
|
-
const createManagerCollaborator = async (
|
|
795
|
-
values: Record<string, string>
|
|
796
|
-
): Promise<ManagerOption | null> => {
|
|
794
|
+
const createManagerCollaborator = async (
|
|
795
|
+
values: Record<string, string>
|
|
796
|
+
): Promise<ManagerOption | null> => {
|
|
797
797
|
const displayName = values.displayName?.trim() ?? '';
|
|
798
798
|
const weeklyCapacityHours = parseNumberInput(
|
|
799
799
|
values.weeklyCapacityHours ?? ''
|
|
@@ -821,8 +821,8 @@ export function ProjectFormScreen({
|
|
|
821
821
|
return next;
|
|
822
822
|
});
|
|
823
823
|
|
|
824
|
-
return toManagerOption(created);
|
|
825
|
-
};
|
|
824
|
+
return toManagerOption(created);
|
|
825
|
+
};
|
|
826
826
|
|
|
827
827
|
const { data: contracts = [], refetch: refetchContracts } = useQuery<
|
|
828
828
|
OperationsContract[]
|
|
@@ -953,13 +953,13 @@ export function ProjectFormScreen({
|
|
|
953
953
|
[availableContracts, form.contractId]
|
|
954
954
|
);
|
|
955
955
|
|
|
956
|
-
const managerOptions = useMemo(
|
|
957
|
-
() =>
|
|
958
|
-
availableCollaborators.map((collaborator) =>
|
|
959
|
-
toManagerOption(collaborator)
|
|
960
|
-
),
|
|
961
|
-
[availableCollaborators]
|
|
962
|
-
);
|
|
956
|
+
const managerOptions = useMemo(
|
|
957
|
+
() =>
|
|
958
|
+
availableCollaborators.map((collaborator) =>
|
|
959
|
+
toManagerOption(collaborator)
|
|
960
|
+
),
|
|
961
|
+
[availableCollaborators]
|
|
962
|
+
);
|
|
963
963
|
|
|
964
964
|
const selectedAssignmentsCount = useMemo(
|
|
965
965
|
() =>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hed-hog/operations",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.349",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"dependencies": {
|
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
"@nestjs/mapped-types": "*",
|
|
12
12
|
"lucide-react": "^0.562.0",
|
|
13
13
|
"@hed-hog/api-types": "0.0.1",
|
|
14
|
-
"@hed-hog/api-locale": "0.0.14",
|
|
15
14
|
"@hed-hog/api": "0.0.8",
|
|
16
|
-
"@hed-hog/
|
|
17
|
-
"@hed-hog/
|
|
15
|
+
"@hed-hog/api-prisma": "0.0.6",
|
|
16
|
+
"@hed-hog/api-locale": "0.0.14",
|
|
18
17
|
"@hed-hog/api-pagination": "0.0.7",
|
|
19
|
-
"@hed-hog/
|
|
18
|
+
"@hed-hog/contact": "0.0.349",
|
|
19
|
+
"@hed-hog/core": "0.0.349"
|
|
20
20
|
},
|
|
21
21
|
"exports": {
|
|
22
22
|
".": {
|
|
@@ -3400,23 +3400,23 @@ export class OperationsService {
|
|
|
3400
3400
|
COUNT(DISTINCT pa.id)::int AS "teamSize"
|
|
3401
3401
|
FROM operations_project p
|
|
3402
3402
|
LEFT JOIN operations_contract c ON c.id = p.contract_id
|
|
3403
|
-
LEFT JOIN operations_collaborator m ON m.id = p.manager_collaborator_id
|
|
3404
|
-
LEFT JOIN person cp ON cp.id = p.client_person_id
|
|
3405
|
-
LEFT JOIN person mp ON mp.id = m.person_id
|
|
3406
|
-
LEFT JOIN LATERAL (
|
|
3407
|
-
SELECT u.photo_id
|
|
3408
|
-
FROM person_user pu
|
|
3409
|
-
JOIN "user" u ON u.id = pu.user_id
|
|
3410
|
-
WHERE pu.person_id = p.client_person_id
|
|
3411
|
-
ORDER BY pu.id ASC
|
|
3412
|
-
LIMIT 1
|
|
3413
|
-
) client_user ON TRUE
|
|
3414
|
-
LEFT JOIN operations_project_assignment pa
|
|
3415
|
-
ON pa.project_id = p.id
|
|
3416
|
-
AND pa.deleted_at IS NULL
|
|
3417
|
-
AND pa.status IN ('planned', 'active')
|
|
3403
|
+
LEFT JOIN operations_collaborator m ON m.id = p.manager_collaborator_id
|
|
3404
|
+
LEFT JOIN person cp ON cp.id = p.client_person_id
|
|
3405
|
+
LEFT JOIN person mp ON mp.id = m.person_id
|
|
3406
|
+
LEFT JOIN LATERAL (
|
|
3407
|
+
SELECT u.photo_id
|
|
3408
|
+
FROM person_user pu
|
|
3409
|
+
JOIN "user" u ON u.id = pu.user_id
|
|
3410
|
+
WHERE pu.person_id = p.client_person_id
|
|
3411
|
+
ORDER BY pu.id ASC
|
|
3412
|
+
LIMIT 1
|
|
3413
|
+
) client_user ON TRUE
|
|
3414
|
+
LEFT JOIN operations_project_assignment pa
|
|
3415
|
+
ON pa.project_id = p.id
|
|
3416
|
+
AND pa.deleted_at IS NULL
|
|
3417
|
+
AND pa.status IN ('planned', 'active')
|
|
3418
3418
|
WHERE ${whereClause}
|
|
3419
|
-
GROUP BY p.id, c.id, m.id, cp.id, mp.id, client_user.photo_id`;
|
|
3419
|
+
GROUP BY p.id, c.id, m.id, cp.id, mp.id, client_user.photo_id`;
|
|
3420
3420
|
|
|
3421
3421
|
if (!pagination) {
|
|
3422
3422
|
return this.queryRows(`${baseQuery} ORDER BY p.name ASC`, params);
|
|
@@ -8941,21 +8941,21 @@ export class OperationsService {
|
|
|
8941
8941
|
MAX(CASE WHEN pa.collaborator_id = $2 THEN pa.id END)::int AS "myAssignmentId",
|
|
8942
8942
|
MAX(CASE WHEN pa.collaborator_id = $2 THEN COALESCE(project_role_locale.name, pa.role_label) END) AS "myRoleLabel",
|
|
8943
8943
|
COUNT(DISTINCT pa.id)::int AS "teamSize"
|
|
8944
|
-
FROM operations_project p
|
|
8945
|
-
LEFT JOIN operations_contract c ON c.id = p.contract_id
|
|
8946
|
-
LEFT JOIN operations_collaborator m ON m.id = p.manager_collaborator_id
|
|
8947
|
-
LEFT JOIN person client_person ON client_person.id = p.client_person_id
|
|
8948
|
-
LEFT JOIN LATERAL (
|
|
8949
|
-
SELECT u.photo_id
|
|
8950
|
-
FROM person_user pu
|
|
8951
|
-
JOIN "user" u ON u.id = pu.user_id
|
|
8952
|
-
WHERE pu.person_id = p.client_person_id
|
|
8953
|
-
ORDER BY pu.id ASC
|
|
8954
|
-
LIMIT 1
|
|
8955
|
-
) client_user ON TRUE
|
|
8956
|
-
LEFT JOIN operations_project_assignment pa
|
|
8957
|
-
ON pa.project_id = p.id
|
|
8958
|
-
AND pa.deleted_at IS NULL
|
|
8944
|
+
FROM operations_project p
|
|
8945
|
+
LEFT JOIN operations_contract c ON c.id = p.contract_id
|
|
8946
|
+
LEFT JOIN operations_collaborator m ON m.id = p.manager_collaborator_id
|
|
8947
|
+
LEFT JOIN person client_person ON client_person.id = p.client_person_id
|
|
8948
|
+
LEFT JOIN LATERAL (
|
|
8949
|
+
SELECT u.photo_id
|
|
8950
|
+
FROM person_user pu
|
|
8951
|
+
JOIN "user" u ON u.id = pu.user_id
|
|
8952
|
+
WHERE pu.person_id = p.client_person_id
|
|
8953
|
+
ORDER BY pu.id ASC
|
|
8954
|
+
LIMIT 1
|
|
8955
|
+
) client_user ON TRUE
|
|
8956
|
+
LEFT JOIN operations_project_assignment pa
|
|
8957
|
+
ON pa.project_id = p.id
|
|
8958
|
+
AND pa.deleted_at IS NULL
|
|
8959
8959
|
LEFT JOIN operations_project_role project_role
|
|
8960
8960
|
ON project_role.id = pa.project_role_id
|
|
8961
8961
|
AND project_role.deleted_at IS NULL
|
|
@@ -8968,7 +8968,7 @@ export class OperationsService {
|
|
|
8968
8968
|
) project_role_locale ON TRUE
|
|
8969
8969
|
WHERE p.id = $1
|
|
8970
8970
|
AND p.deleted_at IS NULL
|
|
8971
|
-
GROUP BY p.id, c.id, m.id, client_person.id, client_user.photo_id`,
|
|
8971
|
+
GROUP BY p.id, c.id, m.id, client_person.id, client_user.photo_id`,
|
|
8972
8972
|
[projectId, actorCollaboratorId ?? null],
|
|
8973
8973
|
);
|
|
8974
8974
|
|
|
@@ -12888,7 +12888,7 @@ export class OperationsService {
|
|
|
12888
12888
|
AND pa.deleted_at IS NULL
|
|
12889
12889
|
AND pa.status IN ('planned', 'active')
|
|
12890
12890
|
WHERE ${whereClause}
|
|
12891
|
-
GROUP BY p.id, c.id, m.id, cp.id, client_user.photo_id`;
|
|
12891
|
+
GROUP BY p.id, c.id, m.id, cp.id, client_user.photo_id`;
|
|
12892
12892
|
|
|
12893
12893
|
if (!pagination) {
|
|
12894
12894
|
return this.queryRows(`${baseQuery} ORDER BY p.name ASC`, params);
|