Refine monthly close cleanup
This commit is contained in:
+69
-1
@@ -701,12 +701,17 @@ async function getStatisticsOverview(period: ParsedPeriod, userId: string) {
|
||||
td.day,
|
||||
td.tracked_minutes,
|
||||
COALESCE(tdb.billed_minutes, 0)::int AS crm_billed_minutes,
|
||||
tdb.billed_minutes IS NOT NULL AS has_crm_value
|
||||
tdb.billed_minutes IS NOT NULL AS has_crm_value,
|
||||
ack.acknowledged_at IS NOT NULL AS missing_crm_acknowledged
|
||||
FROM ticket_day td
|
||||
LEFT JOIN ticket_day_billings tdb
|
||||
ON tdb.ticket_id = td.ticket_id
|
||||
AND tdb.user_id = $3
|
||||
AND tdb.day = td.day
|
||||
LEFT JOIN ticket_day_billing_acknowledgements ack
|
||||
ON ack.ticket_id = td.ticket_id
|
||||
AND ack.user_id = $3
|
||||
AND ack.day = td.day
|
||||
),
|
||||
session_group AS (
|
||||
SELECT
|
||||
@@ -916,6 +921,7 @@ async function getStatisticsOverview(period: ParsedPeriod, userId: string) {
|
||||
FROM ticket_day_billing tdb
|
||||
JOIN session_base sb ON sb.ticket_id = tdb.ticket_id AND sb.day = tdb.day
|
||||
WHERE NOT tdb.has_crm_value
|
||||
AND NOT tdb.missing_crm_acknowledged
|
||||
GROUP BY tdb.ticket_id, tdb.ticket_number, tdb.day, tdb.tracked_minutes, tdb.crm_billed_minutes
|
||||
ORDER BY tdb.day ASC, tdb.ticket_number ASC;
|
||||
`,
|
||||
@@ -2560,9 +2566,71 @@ app.patch("/api/tickets/:ticketId/day-billings/:day", async (req, res) => {
|
||||
[ticketId, userId, day.start, billedMinutes]
|
||||
);
|
||||
|
||||
await query(
|
||||
`
|
||||
DELETE FROM ticket_day_billing_acknowledgements
|
||||
WHERE ticket_id = $1
|
||||
AND user_id = $2
|
||||
AND day = $3::date;
|
||||
`,
|
||||
[ticketId, userId, day.start]
|
||||
);
|
||||
|
||||
res.json({ dayBilling: result.rows[0] });
|
||||
});
|
||||
|
||||
app.patch("/api/tickets/:ticketId/day-billings/:day/acknowledgement", async (req, res) => {
|
||||
const ticketId = parsePositiveInteger(req.params.ticketId, "ticketId");
|
||||
const day = parseDay(req.params.day);
|
||||
const acknowledged = req.body.acknowledged !== false;
|
||||
const userId = currentUser(req).id;
|
||||
|
||||
const sessionResult = await query<{ id: string }>(
|
||||
`
|
||||
SELECT id
|
||||
FROM sessions
|
||||
WHERE ticket_id = $1
|
||||
AND user_id = $2
|
||||
AND (started_at AT TIME ZONE 'Europe/Berlin')::date = $3::date
|
||||
LIMIT 1;
|
||||
`,
|
||||
[ticketId, userId, day.start]
|
||||
);
|
||||
|
||||
if (sessionResult.rowCount === 0) {
|
||||
res.status(404).json({ error: "No sessions found for this ticket and day" });
|
||||
return;
|
||||
}
|
||||
|
||||
if (!acknowledged) {
|
||||
await query(
|
||||
`
|
||||
DELETE FROM ticket_day_billing_acknowledgements
|
||||
WHERE ticket_id = $1
|
||||
AND user_id = $2
|
||||
AND day = $3::date;
|
||||
`,
|
||||
[ticketId, userId, day.start]
|
||||
);
|
||||
|
||||
res.json({ acknowledged: false });
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await query(
|
||||
`
|
||||
INSERT INTO ticket_day_billing_acknowledgements (ticket_id, user_id, day)
|
||||
VALUES ($1, $2, $3::date)
|
||||
ON CONFLICT (ticket_id, user_id, day)
|
||||
DO UPDATE SET acknowledged_at = now()
|
||||
RETURNING day::text AS day, acknowledged_at;
|
||||
`,
|
||||
[ticketId, userId, day.start]
|
||||
);
|
||||
|
||||
res.json({ acknowledged: true, acknowledgement: result.rows[0] });
|
||||
});
|
||||
|
||||
app.post("/api/periods/:periodType/:period/tickets/:ticketId/close", async (req, res) => {
|
||||
parsePeriod(req.params.periodType, req.params.period);
|
||||
parsePositiveInteger(req.params.ticketId, "ticketId");
|
||||
|
||||
Reference in New Issue
Block a user