Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions apps/web-app/app/components/chart/KitchenRevenue.client.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@
<VisLine
:x="x"
:y="y"
color="var(--ui-secondary)"
:color="color"
:line-dash-array="lineDashArray"
/>
<VisArea
:x="x"
:y="y"
:y="yArea"
color="var(--ui-secondary)"
:opacity="0.1"
/>
Expand Down Expand Up @@ -55,12 +56,13 @@ type DataRecord = {
date: Date
total: number
checks: number
commonTotal: number
}

const { period, range, values } = defineProps<{
period: Period
range: Range
values: { date: string, total: number, checks: number }[]
values: { date: string, total: number, checks: number, commonTotal: number }[]
}>()

const cardRef = useTemplateRef<HTMLElement | null>('cardRef')
Expand All @@ -84,12 +86,20 @@ watch([() => period, () => range, () => values], () => {
date,
total: value?.total ?? 0,
checks: value?.checks ?? 0,
commonTotal: value?.commonTotal ?? 0,
}
})
}, { immediate: true })

const x = (_: DataRecord, i: number) => i
const y = (d: DataRecord) => d.total
const y = [
(d: DataRecord) => d.total,
(d: DataRecord) => d.commonTotal,
]
const yArea = (d: DataRecord) => d.total

const color = (_: DataRecord, i: number) => ['var(--ui-secondary)', 'var(--ui-secondary)'][i]
const lineDashArray = (_: DataRecord, i: number) => [i === 0 ? undefined : 4]

const total = computed(() => data.value.reduce((acc: number, { total }) => acc + total, 0))

Expand All @@ -111,7 +121,7 @@ function xTicks(i: number) {
return formatDate(data.value[i].date)
}

const template = (d: DataRecord) => `${formatDate(d.date)}: ${formatNumber(d.total)}, ${d.checks} ${pluralizationRu(d.checks, ['чек', 'чека', 'чеков'])}`
const template = (d: DataRecord) => `${formatDate(d.date)}, ${format(d.date, 'eeeeee', { locale: ru })}: ${d.checks} ${pluralizationRu(d.checks, ['чек', 'чека', 'чеков'])}<br> Выручка: ${formatNumber(d.total)}<br> Средняя: ${formatNumber(d.commonTotal)}`
</script>

<style scoped>
Expand Down
2 changes: 1 addition & 1 deletion apps/web-app/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default defineNuxtConfig({
tasks: true,
},
scheduledTasks: {
'* * * * *': ['task:auto-create', 'kitchen:average-update'], // Every minute
'* * * * *': ['task:auto-create'], // Every minute
'0 * * * *': ['kitchen:revenue-update'], // Every hour
'0 0 * * *': ['kitchen:rating-update'], // Every day
},
Expand Down
22 changes: 21 additions & 1 deletion apps/web-app/server/api/kitchen/revenue/iiko-daily.post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ async function parseFileAndUpdateData(file: MultiPartData) {
})
}

const parsedKitchens: { name: string, total: number, checks: number }[] = []
const parsedKitchens: { name: string, total: number, checks: number, averageCheck: number, commonAverageCheck: number, commonTotal: number }[] = []

for (const row of dataRows) {
const name = row[indexOfName]
Expand All @@ -132,13 +132,27 @@ async function parseFileAndUpdateData(file: MultiPartData) {
continue
}

const averageCheck = Math.round(total / checks)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add validation for division by zero.

The average check calculation could fail if checks is 0, leading to Infinity or NaN values.

Add validation to handle zero checks:

+    if (checks === 0) {
+      continue
+    }
+
     const averageCheck = Math.round(total / checks)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const averageCheck = Math.round(total / checks)
if (checks === 0) {
continue
}
const averageCheck = Math.round(total / checks)
🤖 Prompt for AI Agents
In apps/web-app/server/api/kitchen/revenue/iiko-daily.post.ts at line 135, the
calculation of averageCheck divides total by checks without checking if checks
is zero, which can cause Infinity or NaN results. Add a validation before the
division to check if checks is zero; if so, set averageCheck to zero or an
appropriate default value to avoid invalid calculations.


parsedKitchens.push({
name,
total,
checks,
averageCheck,
commonAverageCheck: 0,
commonTotal: 0,
})
}

// Update common data
const commonAverageCheck = Math.round(parsedKitchens.reduce((acc, curr) => acc + curr.averageCheck, 0) / parsedKitchens.length)
const commonTotal = Math.round(parsedKitchens.reduce((acc, curr) => acc + curr.total, 0) / parsedKitchens.length)
Comment on lines +148 to +149
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add validation for empty kitchen arrays.

The common value calculations could fail with division by zero if parsedKitchens.length is 0.

Add validation to handle empty arrays:

+  if (parsedKitchens.length === 0) {
+    return { rowsUpdated: 0, errors: ['No valid kitchen data found'] }
+  }
+
   // Update common data
   const commonAverageCheck = Math.round(parsedKitchens.reduce((acc, curr) => acc + curr.averageCheck, 0) / parsedKitchens.length)
   const commonTotal = Math.round(parsedKitchens.reduce((acc, curr) => acc + curr.total, 0) / parsedKitchens.length)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const commonAverageCheck = Math.round(parsedKitchens.reduce((acc, curr) => acc + curr.averageCheck, 0) / parsedKitchens.length)
const commonTotal = Math.round(parsedKitchens.reduce((acc, curr) => acc + curr.total, 0) / parsedKitchens.length)
if (parsedKitchens.length === 0) {
return { rowsUpdated: 0, errors: ['No valid kitchen data found'] }
}
// Update common data
const commonAverageCheck = Math.round(
parsedKitchens.reduce((acc, curr) => acc + curr.averageCheck, 0) / parsedKitchens.length
)
const commonTotal = Math.round(
parsedKitchens.reduce((acc, curr) => acc + curr.total, 0) / parsedKitchens.length
)
🤖 Prompt for AI Agents
In apps/web-app/server/api/kitchen/revenue/iiko-daily.post.ts around lines 148
to 149, the code calculates averages by dividing sums by parsedKitchens.length
without checking if the array is empty, which can cause division by zero errors.
Add a validation before these calculations to check if parsedKitchens.length is
greater than zero; if it is zero, set commonAverageCheck and commonTotal to a
safe default value like 0 to avoid runtime errors.


for (const kitchen of parsedKitchens) {
kitchen.commonAverageCheck = commonAverageCheck
kitchen.commonTotal = commonTotal
}

// Every kitchen: find in DB and add amount for this day
const kitchens = await repository.kitchen.list()
let rowsUpdated = 0
Expand All @@ -155,11 +169,17 @@ async function parseFileAndUpdateData(file: MultiPartData) {
date: dateOnly,
total: kitchen.total,
checks: kitchen.checks,
averageCheck: kitchen.averageCheck,
commonAverageCheck: kitchen.commonAverageCheck,
commonTotal: kitchen.commonTotal,
})
} else {
await repository.kitchen.updateRevenue(revenue.id, {
total: kitchen.total,
checks: kitchen.checks,
averageCheck: kitchen.averageCheck,
commonAverageCheck: kitchen.commonAverageCheck,
commonTotal: kitchen.commonTotal,
})
}

Expand Down
7 changes: 0 additions & 7 deletions apps/web-app/server/tasks/kitchen/average-update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,11 @@ export default defineTask({
try {
const revenuesToUpdate = await repository.kitchen.listRevenuesToUpdate()
for (const revenue of revenuesToUpdate) {
// Average check
const averageCheck = Math.round(revenue.total / revenue.checks)

// common
const allRevenuesThisPeriod = await repository.kitchen.listRevenuesForDate(revenue.date)
const commonAverageCheck = Math.round(allRevenuesThisPeriod.reduce((acc, curr) => acc + curr.averageCheck, 0) / allRevenuesThisPeriod.length)
const commonTotal = Math.round(allRevenuesThisPeriod.reduce((acc, curr) => acc + curr.total, 0) / allRevenuesThisPeriod.length)

await repository.kitchen.updateRevenue(revenue.id, {
averageCheck,
commonAverageCheck,
commonTotal,
})
}
} catch (error) {
Expand Down
9 changes: 4 additions & 5 deletions apps/web-app/server/tasks/kitchen/revenue-update.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { repository } from '@roll-stack/database'
import { endOfWeek, startOfWeek } from 'date-fns'

const logger = useLogger('kitchen:revenue-update')

export default defineTask({
meta: {
name: 'kitchen:revenue-update',
Expand All @@ -19,12 +17,13 @@ export default defineTask({
const thisMonday = startOfWeek(utcNow, { weekStartsOn: 1 })
const thisSunday = endOfWeek(utcNow, { weekStartsOn: 1 })

logger.log(thisMonday, thisSunday)

for (const kitchen of kitchens) {
const revenues = await repository.kitchen.listRevenuesByKitchenForPeriod(kitchen.id, thisMonday, thisSunday)

const revenueForThisWeek = revenues.reduce((acc, curr) => acc + curr.total, 0)
const revenueForThisWeek = Math.round(revenues.reduce((acc, curr) => acc + curr.total, 0))
if (revenueForThisWeek === kitchen.revenueForThisWeek) {
continue
}

await repository.kitchen.update(kitchen.id, {
revenueForThisWeek,
Expand Down
3 changes: 1 addition & 2 deletions packages/database/src/repository/kitchen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,7 @@ export class Kitchen {
static async listRevenuesToUpdate() {
return useDatabase().query.kitchenRevenues.findMany({
where: (revenues, { eq, or }) => or(
eq(revenues.averageCheck, 0),
eq(revenues.commonTotal, 0),
eq(revenues.commonAverageCheck, 0),
),
limit: 50,
})
Expand Down