@hed-hog/operations 0.0.325 → 0.0.327

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.
Files changed (32) hide show
  1. package/dist/controllers/operations-collaborators.controller.d.ts +5 -0
  2. package/dist/controllers/operations-collaborators.controller.d.ts.map +1 -1
  3. package/dist/operations.service.d.ts +9 -1
  4. package/dist/operations.service.d.ts.map +1 -1
  5. package/dist/operations.service.js +140 -26
  6. package/dist/operations.service.js.map +1 -1
  7. package/hedhog/data/integration_event_catalog.yaml +313 -0
  8. package/hedhog/data/setting_group.yaml +21 -0
  9. package/hedhog/frontend/app/_components/collaborator-form-screen.tsx.ejs +410 -23
  10. package/hedhog/frontend/app/_components/my-project-summary-screen.tsx.ejs +504 -375
  11. package/hedhog/frontend/app/_components/project-details-screen.tsx.ejs +258 -230
  12. package/hedhog/frontend/app/_components/task-detail-sheet.tsx.ejs +225 -162
  13. package/hedhog/frontend/app/_components/task-form-sheet.tsx.ejs +484 -230
  14. package/hedhog/frontend/app/_lib/api.ts.ejs +13 -4
  15. package/hedhog/frontend/app/_lib/hooks/use-mention-items.ts.ejs +28 -0
  16. package/hedhog/frontend/app/_lib/types.ts.ejs +30 -29
  17. package/hedhog/frontend/app/my-tasks/page.tsx.ejs +347 -236
  18. package/hedhog/frontend/app/reports/projects/page.tsx.ejs +31 -7
  19. package/hedhog/frontend/messages/en.json +38 -55
  20. package/hedhog/frontend/messages/en.json.ejs +21 -4
  21. package/hedhog/frontend/messages/pt.json +36 -55
  22. package/hedhog/frontend/messages/pt.json.ejs +14 -3
  23. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/types.d.ts +1 -0
  24. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/types.d.ts.map +1 -1
  25. package/hedhog/frontend/src/app/(app)/(libraries)/operations/_lib/types.ts +1 -0
  26. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/types.d.ts +1 -0
  27. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/types.d.ts.map +1 -1
  28. package/hedhog/frontend/src/app/(app)/(libraries)/operations/operations/_lib/types.ts +1 -0
  29. package/hedhog/table/operations_collaborator.yaml +5 -0
  30. package/hedhog/table/operations_collaborator_compensation_history.yaml +4 -0
  31. package/package.json +5 -5
  32. package/src/operations.service.ts +202 -26
@@ -997,7 +997,7 @@ let OperationsService = OperationsService_1 = class OperationsService {
997
997
  throw new common_1.BadRequestException('Field "personId" is required.');
998
998
  }
999
999
  const collaboratorId = await this.prisma.$transaction(async (tx) => {
1000
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2;
1000
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6;
1001
1001
  const normalizedCode = String((_a = data.code) !== null && _a !== void 0 ? _a : '').trim() ||
1002
1002
  (await this.generateCollaboratorCode(tx));
1003
1003
  const resolvedDepartment = await this.resolveDepartmentReference(tx, {
@@ -1053,11 +1053,23 @@ let OperationsService = OperationsService_1 = class OperationsService {
1053
1053
  });
1054
1054
  }
1055
1055
  if (data.compensationAmount != null) {
1056
- await this.insertCollaboratorCompensationHistory(tx, createdCollaboratorId, Number(data.compensationAmount), actor.userId, null);
1056
+ await this.insertCollaboratorCompensationHistory(tx, createdCollaboratorId, Number(data.compensationAmount), actor.userId, (_3 = data.compensationNotes) !== null && _3 !== void 0 ? _3 : null, (_4 = data.compensationEffectiveDate) !== null && _4 !== void 0 ? _4 : null);
1057
+ }
1058
+ if (data.hourlyRate != null) {
1059
+ await tx.$executeRawUnsafe(`UPDATE operations_collaborator SET hourly_rate = $1 WHERE id = $2`, Number(data.hourlyRate), createdCollaboratorId);
1060
+ await this.insertCollaboratorCompensationHistory(tx, createdCollaboratorId, Number(data.hourlyRate), actor.userId, (_5 = data.compensationNotes) !== null && _5 !== void 0 ? _5 : null, (_6 = data.compensationEffectiveDate) !== null && _6 !== void 0 ? _6 : null, 'hourly_rate');
1057
1061
  }
1058
1062
  return createdCollaboratorId;
1059
1063
  });
1060
- return this.getCollaboratorByIdForUser(userId, collaboratorId);
1064
+ const result = await this.getCollaboratorByIdForUser(userId, collaboratorId);
1065
+ await this.integrationApi.publishEvent({
1066
+ eventName: 'operations.collaborator.created',
1067
+ sourceModule: 'operations',
1068
+ aggregateType: 'collaborator',
1069
+ aggregateId: String(collaboratorId),
1070
+ payload: { id: collaboratorId, displayName: resolvedDisplayName, status: normalizedStatus },
1071
+ }).catch(() => null);
1072
+ return result;
1061
1073
  }
1062
1074
  async updateCollaborator(userId, collaboratorId, data) {
1063
1075
  var _a, _b, _c, _d, _e;
@@ -1080,34 +1092,41 @@ let OperationsService = OperationsService_1 = class OperationsService {
1080
1092
  }
1081
1093
  this.pushUpdate(updates, params, 'level_label', data.levelLabel);
1082
1094
  this.pushUpdate(updates, params, 'weekly_capacity_hours', data.weeklyCapacityHours);
1095
+ this.pushUpdate(updates, params, 'hourly_rate', data.hourlyRate);
1083
1096
  this.pushUpdate(updates, params, 'status', normalizedStatus, 'operations_collaborator_status_ef779877d4_enum');
1084
1097
  this.pushUpdate(updates, params, 'joined_at', data.joinedAt, 'date');
1085
1098
  this.pushUpdate(updates, params, 'left_at', data.leftAt, 'date');
1086
1099
  this.pushUpdate(updates, params, 'notes', data.notes);
1100
+ let currentHourlyRate = null;
1087
1101
  await this.prisma.$transaction(async (tx) => {
1088
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
1102
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
1103
+ if (data.hourlyRate !== undefined && data.hourlyRate !== null) {
1104
+ const curr = (await tx.$queryRawUnsafe(`SELECT hourly_rate AS "hourlyRate" FROM operations_collaborator WHERE id = $1`, collaboratorId));
1105
+ currentHourlyRate =
1106
+ ((_a = curr[0]) === null || _a === void 0 ? void 0 : _a.hourlyRate) != null ? Number(curr[0].hourlyRate) : null;
1107
+ }
1089
1108
  if (data.collaboratorType !== undefined ||
1090
1109
  data.collaboratorTypeId !== undefined ||
1091
1110
  data.collaboratorTypeSlug !== undefined) {
1092
1111
  const resolvedCollaboratorType = await this.resolveCollaboratorTypeReference(tx, {
1093
- collaboratorTypeId: (_a = data.collaboratorTypeId) !== null && _a !== void 0 ? _a : null,
1094
- collaboratorTypeSlug: (_c = (_b = data.collaboratorTypeSlug) !== null && _b !== void 0 ? _b : data.collaboratorType) !== null && _c !== void 0 ? _c : null,
1112
+ collaboratorTypeId: (_b = data.collaboratorTypeId) !== null && _b !== void 0 ? _b : null,
1113
+ collaboratorTypeSlug: (_d = (_c = data.collaboratorTypeSlug) !== null && _c !== void 0 ? _c : data.collaboratorType) !== null && _d !== void 0 ? _d : null,
1095
1114
  });
1096
- this.pushUpdate(updates, params, 'collaborator_type_id', (_d = resolvedCollaboratorType === null || resolvedCollaboratorType === void 0 ? void 0 : resolvedCollaboratorType.id) !== null && _d !== void 0 ? _d : null);
1115
+ this.pushUpdate(updates, params, 'collaborator_type_id', (_e = resolvedCollaboratorType === null || resolvedCollaboratorType === void 0 ? void 0 : resolvedCollaboratorType.id) !== null && _e !== void 0 ? _e : null);
1097
1116
  }
1098
1117
  if (data.departmentId !== undefined) {
1099
1118
  const resolvedDepartment = await this.resolveDepartmentReference(tx, {
1100
- departmentId: (_e = data.departmentId) !== null && _e !== void 0 ? _e : null,
1119
+ departmentId: (_f = data.departmentId) !== null && _f !== void 0 ? _f : null,
1101
1120
  });
1102
- this.pushUpdate(updates, params, 'department_id', (_f = resolvedDepartment === null || resolvedDepartment === void 0 ? void 0 : resolvedDepartment.id) !== null && _f !== void 0 ? _f : null);
1121
+ this.pushUpdate(updates, params, 'department_id', (_g = resolvedDepartment === null || resolvedDepartment === void 0 ? void 0 : resolvedDepartment.id) !== null && _g !== void 0 ? _g : null);
1103
1122
  }
1104
1123
  if (data.title !== undefined || data.jobTitleId !== undefined) {
1105
1124
  const resolvedJobTitle = await this.resolveJobTitleReference(tx, {
1106
- jobTitleId: (_g = data.jobTitleId) !== null && _g !== void 0 ? _g : null,
1125
+ jobTitleId: (_h = data.jobTitleId) !== null && _h !== void 0 ? _h : null,
1107
1126
  jobTitleName: data.title,
1108
1127
  });
1109
- this.pushUpdate(updates, params, 'job_title_id', (_h = resolvedJobTitle === null || resolvedJobTitle === void 0 ? void 0 : resolvedJobTitle.id) !== null && _h !== void 0 ? _h : null);
1110
- this.pushUpdate(updates, params, 'title', (_j = resolvedJobTitle === null || resolvedJobTitle === void 0 ? void 0 : resolvedJobTitle.name) !== null && _j !== void 0 ? _j : this.normalizeOptionalText(data.title));
1128
+ this.pushUpdate(updates, params, 'job_title_id', (_j = resolvedJobTitle === null || resolvedJobTitle === void 0 ? void 0 : resolvedJobTitle.id) !== null && _j !== void 0 ? _j : null);
1129
+ this.pushUpdate(updates, params, 'title', (_k = resolvedJobTitle === null || resolvedJobTitle === void 0 ? void 0 : resolvedJobTitle.name) !== null && _k !== void 0 ? _k : this.normalizeOptionalText(data.title));
1111
1130
  }
1112
1131
  if (updates.length) {
1113
1132
  params.push(collaboratorId);
@@ -1125,6 +1144,7 @@ let OperationsService = OperationsService_1 = class OperationsService {
1125
1144
  if (data.compensationAmount !== undefined ||
1126
1145
  data.contractDescription !== undefined ||
1127
1146
  data.autoGenerateContractDraft !== undefined ||
1147
+ data.hourlyRate !== undefined ||
1128
1148
  data.joinedAt !== undefined ||
1129
1149
  data.weeklyCapacityHours !== undefined ||
1130
1150
  data.supervisorCollaboratorId !== undefined ||
@@ -1134,14 +1154,47 @@ let OperationsService = OperationsService_1 = class OperationsService {
1134
1154
  data.code !== undefined ||
1135
1155
  data.personId !== undefined ||
1136
1156
  data.displayName !== undefined) {
1157
+ let currentBudgetAmount = null;
1158
+ if (data.compensationAmount !== undefined &&
1159
+ data.compensationAmount !== null) {
1160
+ const hiringContracts = (await tx.$queryRawUnsafe(`SELECT budget_amount AS "budgetAmount"
1161
+ FROM operations_contract
1162
+ WHERE related_collaborator_id = $1
1163
+ AND origin_type = 'employee_hiring'
1164
+ AND deleted_at IS NULL
1165
+ ORDER BY created_at DESC
1166
+ LIMIT 1`, collaboratorId));
1167
+ currentBudgetAmount =
1168
+ ((_l = hiringContracts[0]) === null || _l === void 0 ? void 0 : _l.budgetAmount) != null
1169
+ ? Number(hiringContracts[0].budgetAmount)
1170
+ : null;
1171
+ }
1137
1172
  await this.syncHiringContractDraft(tx, actor.userId, collaboratorId, data);
1138
1173
  if (data.compensationAmount !== undefined &&
1139
1174
  data.compensationAmount !== null) {
1140
- await this.insertCollaboratorCompensationHistory(tx, collaboratorId, Number(data.compensationAmount), actor.userId, null);
1175
+ const newAmount = Number(data.compensationAmount);
1176
+ if (currentBudgetAmount === null ||
1177
+ newAmount !== currentBudgetAmount) {
1178
+ await this.insertCollaboratorCompensationHistory(tx, collaboratorId, newAmount, actor.userId, (_m = data.compensationNotes) !== null && _m !== void 0 ? _m : null, (_o = data.compensationEffectiveDate) !== null && _o !== void 0 ? _o : null);
1179
+ }
1180
+ }
1181
+ if (data.hourlyRate !== undefined && data.hourlyRate !== null) {
1182
+ const newRate = Number(data.hourlyRate);
1183
+ if (currentHourlyRate === null || newRate !== currentHourlyRate) {
1184
+ await this.insertCollaboratorCompensationHistory(tx, collaboratorId, newRate, actor.userId, (_p = data.compensationNotes) !== null && _p !== void 0 ? _p : null, (_q = data.compensationEffectiveDate) !== null && _q !== void 0 ? _q : null, 'hourly_rate');
1185
+ }
1141
1186
  }
1142
1187
  }
1143
1188
  });
1144
- return this.getCollaboratorByIdForUser(userId, collaboratorId);
1189
+ const collaboratorResult = await this.getCollaboratorByIdForUser(userId, collaboratorId);
1190
+ await this.integrationApi.publishEvent({
1191
+ eventName: 'operations.collaborator.updated',
1192
+ sourceModule: 'operations',
1193
+ aggregateType: 'collaborator',
1194
+ aggregateId: String(collaboratorId),
1195
+ payload: { id: collaboratorId, displayName: data.displayName, status: data.status },
1196
+ }).catch(() => null);
1197
+ return collaboratorResult;
1145
1198
  }
1146
1199
  async updateCollaboratorProjectAssignment(collaboratorId, projectId, data) {
1147
1200
  var _a, _b, _c, _d, _e, _f;
@@ -1210,6 +1263,7 @@ let OperationsService = OperationsService_1 = class OperationsService {
1210
1263
  h.actor_user_id AS "actorUserId",
1211
1264
  u.name AS "actorName",
1212
1265
  h.notes,
1266
+ h.amount_type AS "amountType",
1213
1267
  h.created_at AS "createdAt"
1214
1268
  FROM operations_collaborator_compensation_history h
1215
1269
  LEFT JOIN "user" u ON u.id = h.actor_user_id
@@ -1714,7 +1768,7 @@ let OperationsService = OperationsService_1 = class OperationsService {
1714
1768
  return this.buildPaginationResult(rows.map((row) => (Object.assign(Object.assign({}, row), { label: [row.name, row.projectName].filter(Boolean).join(' • ') }))), Number((_b = totalRow === null || totalRow === void 0 ? void 0 : totalRow.total) !== null && _b !== void 0 ? _b : 0), pagination.page, pagination.pageSize);
1715
1769
  }
1716
1770
  async createTask(userId, data) {
1717
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
1771
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
1718
1772
  const actor = await this.getActorContext(userId);
1719
1773
  if (!actor.isCollaborator && !actor.isDirector && !actor.isSupervisor) {
1720
1774
  throw new common_1.ForbiddenException('Operations collaborator access is required.');
@@ -1790,7 +1844,15 @@ let OperationsService = OperationsService_1 = class OperationsService {
1790
1844
  (_m = data.position) !== null && _m !== void 0 ? _m : nextPosition,
1791
1845
  (_o = data.tags) !== null && _o !== void 0 ? _o : null,
1792
1846
  ]);
1793
- return this.getProjectBoardTask((_p = created === null || created === void 0 ? void 0 : created.id) !== null && _p !== void 0 ? _p : 0);
1847
+ const task = await this.getProjectBoardTask((_p = created === null || created === void 0 ? void 0 : created.id) !== null && _p !== void 0 ? _p : 0);
1848
+ await this.integrationApi.publishEvent({
1849
+ eventName: 'operations.task.created',
1850
+ sourceModule: 'operations',
1851
+ aggregateType: 'task',
1852
+ aggregateId: String((_q = created === null || created === void 0 ? void 0 : created.id) !== null && _q !== void 0 ? _q : 0),
1853
+ payload: { id: created === null || created === void 0 ? void 0 : created.id, projectId, name, status: (_r = data.status) !== null && _r !== void 0 ? _r : 'todo', priority: (_s = data.priority) !== null && _s !== void 0 ? _s : 'medium' },
1854
+ }).catch(() => null);
1855
+ return task;
1794
1856
  }
1795
1857
  async updateTask(userId, taskId, data) {
1796
1858
  const actor = await this.getActorContext(userId);
@@ -1848,7 +1910,15 @@ let OperationsService = OperationsService_1 = class OperationsService {
1848
1910
  ? this.normalizeOptionalText(data.description)
1849
1911
  : ((_d = current.description) !== null && _d !== void 0 ? _d : null), (_e = data.priority) !== null && _e !== void 0 ? _e : current.priority, nextStatus, data.dueDate !== undefined ? ((_f = data.dueDate) !== null && _f !== void 0 ? _f : null) : current.dueDate, data.estimateHours !== undefined ? ((_g = data.estimateHours) !== null && _g !== void 0 ? _g : null) : current.estimateHours, data.position !== undefined ? data.position : current.position, data.tags !== undefined ? ((_h = data.tags) !== null && _h !== void 0 ? _h : null) : current.tags, nextArchived, taskId, Boolean(current.deletedAt));
1850
1912
  });
1851
- return this.getProjectBoardTask(taskId);
1913
+ const taskResult = await this.getProjectBoardTask(taskId);
1914
+ await this.integrationApi.publishEvent({
1915
+ eventName: 'operations.task.updated',
1916
+ sourceModule: 'operations',
1917
+ aggregateType: 'task',
1918
+ aggregateId: String(taskId),
1919
+ payload: { id: taskId, name: data.name, status: data.status },
1920
+ }).catch(() => null);
1921
+ return taskResult;
1852
1922
  }
1853
1923
  async removeTask(userId, taskId, permanent = false) {
1854
1924
  const actor = await this.getActorContext(userId);
@@ -1869,6 +1939,13 @@ let OperationsService = OperationsService_1 = class OperationsService {
1869
1939
  WHERE id = $1
1870
1940
  AND deleted_at IS NULL`, taskId);
1871
1941
  });
1942
+ await this.integrationApi.publishEvent({
1943
+ eventName: 'operations.task.deleted',
1944
+ sourceModule: 'operations',
1945
+ aggregateType: 'task',
1946
+ aggregateId: String(taskId),
1947
+ payload: { id: taskId, projectId: current.projectId, permanent },
1948
+ }).catch(() => null);
1872
1949
  return { success: true };
1873
1950
  }
1874
1951
  async listTaskFiles(userId, taskId) {
@@ -1972,7 +2049,7 @@ let OperationsService = OperationsService_1 = class OperationsService {
1972
2049
  return createdComment;
1973
2050
  }
1974
2051
  async updateTaskComment(userId, taskId, commentId, content) {
1975
- var _a;
2052
+ var _a, _b;
1976
2053
  const actor = await this.getActorContext(userId);
1977
2054
  if (!actor.isCollaborator && !actor.isDirector && !actor.isSupervisor) {
1978
2055
  throw new common_1.ForbiddenException('Operations collaborator access is required.');
@@ -1983,7 +2060,7 @@ let OperationsService = OperationsService_1 = class OperationsService {
1983
2060
  if (!normalizedContent) {
1984
2061
  throw new common_1.BadRequestException('Comment content is required.');
1985
2062
  }
1986
- const rows = await this.queryRows(`SELECT id, actor_collaborator_id AS "actorCollaboratorId"
2063
+ const rows = await this.queryRows(`SELECT id, actor_collaborator_id AS "actorCollaboratorId", created_at AS "createdAt"
1987
2064
  FROM operations_task_comment
1988
2065
  WHERE id = $1 AND task_id = $2`, [commentId, taskId]);
1989
2066
  const row = rows[0];
@@ -1993,20 +2070,29 @@ let OperationsService = OperationsService_1 = class OperationsService {
1993
2070
  if (row.actorCollaboratorId !== actor.collaboratorId) {
1994
2071
  throw new common_1.ForbiddenException('You can only edit your own comments.');
1995
2072
  }
2073
+ const editSettings = await this.settingService.getSettingValues(['operations.comment-edit-window']);
2074
+ const editWindowMinutes = Number((_a = editSettings['operations.comment-edit-window']) !== null && _a !== void 0 ? _a : 5);
2075
+ if (editWindowMinutes > 0) {
2076
+ const diffMinutes = (Date.now() - new Date(row.createdAt).getTime()) / 60000;
2077
+ if (diffMinutes > editWindowMinutes) {
2078
+ throw new common_1.ForbiddenException(`Comments can only be edited within ${editWindowMinutes} minute(s) of posting.`);
2079
+ }
2080
+ }
1996
2081
  await this.queryRows(`UPDATE operations_task_comment
1997
2082
  SET content = $1, updated_at = NOW()
1998
2083
  WHERE id = $2`, [normalizedContent, commentId]);
1999
2084
  const comments = await this.listTaskComments(userId, taskId);
2000
- return (_a = comments.find((c) => c.id === commentId)) !== null && _a !== void 0 ? _a : null;
2085
+ return (_b = comments.find((c) => c.id === commentId)) !== null && _b !== void 0 ? _b : null;
2001
2086
  }
2002
2087
  async removeTaskComment(userId, taskId, commentId) {
2088
+ var _a;
2003
2089
  const actor = await this.getActorContext(userId);
2004
2090
  if (!actor.isCollaborator && !actor.isDirector && !actor.isSupervisor) {
2005
2091
  throw new common_1.ForbiddenException('Operations collaborator access is required.');
2006
2092
  }
2007
2093
  const current = await this.getTaskRecordForActor(this.prisma, actor, taskId);
2008
2094
  await this.assertProjectAccess(actor, current.projectId);
2009
- const rows = await this.queryRows(`SELECT id, actor_collaborator_id AS "actorCollaboratorId"
2095
+ const rows = await this.queryRows(`SELECT id, actor_collaborator_id AS "actorCollaboratorId", created_at AS "createdAt"
2010
2096
  FROM operations_task_comment
2011
2097
  WHERE id = $1 AND task_id = $2`, [commentId, taskId]);
2012
2098
  const row = rows[0];
@@ -2016,6 +2102,14 @@ let OperationsService = OperationsService_1 = class OperationsService {
2016
2102
  if (row.actorCollaboratorId !== actor.collaboratorId) {
2017
2103
  throw new common_1.ForbiddenException('You can only delete your own comments.');
2018
2104
  }
2105
+ const deleteSettings = await this.settingService.getSettingValues(['operations.comment-edit-window']);
2106
+ const deleteWindowMinutes = Number((_a = deleteSettings['operations.comment-edit-window']) !== null && _a !== void 0 ? _a : 5);
2107
+ if (deleteWindowMinutes > 0) {
2108
+ const diffMinutes = (Date.now() - new Date(row.createdAt).getTime()) / 60000;
2109
+ if (diffMinutes > deleteWindowMinutes) {
2110
+ throw new common_1.ForbiddenException(`Comments can only be deleted within ${deleteWindowMinutes} minute(s) of posting.`);
2111
+ }
2112
+ }
2019
2113
  await this.queryRows(`DELETE FROM operations_task_comment WHERE id = $1`, [commentId]);
2020
2114
  return { success: true };
2021
2115
  }
@@ -2285,6 +2379,7 @@ let OperationsService = OperationsService_1 = class OperationsService {
2285
2379
  return this.getProjectDetails(projectId, actor.collaboratorId);
2286
2380
  }
2287
2381
  async createProject(userId, data) {
2382
+ var _a;
2288
2383
  const actor = await this.getActorContext(userId);
2289
2384
  this.ensureDirector(actor);
2290
2385
  this.requireFields(data, ['code', 'name']);
@@ -2320,7 +2415,15 @@ let OperationsService = OperationsService_1 = class OperationsService {
2320
2415
  }
2321
2416
  return projectId;
2322
2417
  });
2323
- return this.getProjectById(userId, createdProjectId);
2418
+ const result = await this.getProjectById(userId, createdProjectId);
2419
+ await this.integrationApi.publishEvent({
2420
+ eventName: 'operations.project.created',
2421
+ sourceModule: 'operations',
2422
+ aggregateType: 'project',
2423
+ aggregateId: String(createdProjectId),
2424
+ payload: { id: createdProjectId, code: data.code, name: data.name, status: (_a = data.status) !== null && _a !== void 0 ? _a : 'planning' },
2425
+ }).catch(() => null);
2426
+ return result;
2324
2427
  }
2325
2428
  async updateProject(userId, projectId, data) {
2326
2429
  const actor = await this.getActorContext(userId);
@@ -2373,7 +2476,15 @@ let OperationsService = OperationsService_1 = class OperationsService {
2373
2476
  }
2374
2477
  }
2375
2478
  });
2376
- return this.getProjectById(userId, projectId);
2479
+ const projectResult = await this.getProjectById(userId, projectId);
2480
+ await this.integrationApi.publishEvent({
2481
+ eventName: 'operations.project.updated',
2482
+ sourceModule: 'operations',
2483
+ aggregateType: 'project',
2484
+ aggregateId: String(projectId),
2485
+ payload: { id: projectId, name: data.name, status: data.status },
2486
+ }).catch(() => null);
2487
+ return projectResult;
2377
2488
  }
2378
2489
  async listContracts(userId, filters = {}) {
2379
2490
  var _a, _b;
@@ -4766,6 +4877,7 @@ let OperationsService = OperationsService_1 = class OperationsService {
4766
4877
  COALESCE(NULLIF(job_title_record.name, ''), NULLIF(c.title, '')) AS "title",
4767
4878
  c.level_label AS "levelLabel",
4768
4879
  c.weekly_capacity_hours AS "weeklyCapacityHours",
4880
+ c.hourly_rate AS "hourlyRate",
4769
4881
  c.status,
4770
4882
  c.joined_at AS "joinedAt",
4771
4883
  c.left_at AS "leftAt",
@@ -6222,16 +6334,18 @@ let OperationsService = OperationsService_1 = class OperationsService {
6222
6334
  $1, $2, $3, $4, $5, NOW()
6223
6335
  )`, contractId, actorUserId, action, note, metadataJson !== null && metadataJson !== void 0 ? metadataJson : null);
6224
6336
  }
6225
- async insertCollaboratorCompensationHistory(client, collaboratorId, amount, actorUserId, notes) {
6337
+ async insertCollaboratorCompensationHistory(client, collaboratorId, amount, actorUserId, notes, effectiveDate, amountType = 'salary') {
6226
6338
  await client.$executeRawUnsafe(`INSERT INTO operations_collaborator_compensation_history (
6227
6339
  collaborator_id,
6228
6340
  amount,
6229
6341
  actor_user_id,
6230
6342
  notes,
6343
+ effective_date,
6344
+ amount_type,
6231
6345
  created_at
6232
6346
  ) VALUES (
6233
- $1, $2, $3, $4, NOW()
6234
- )`, collaboratorId, amount, actorUserId, notes !== null && notes !== void 0 ? notes : null);
6347
+ $1, $2, $3, $4, $5::date, $6::operations_collaborator_compensation_history_am_f803c4196e_enum, NOW()
6348
+ )`, collaboratorId, amount, actorUserId, notes !== null && notes !== void 0 ? notes : null, effectiveDate !== null && effectiveDate !== void 0 ? effectiveDate : null, amountType);
6235
6349
  }
6236
6350
  async generateCollaboratorCode(client) {
6237
6351
  for (let attempt = 0; attempt < 5; attempt += 1) {