fix report

This commit is contained in:
Efril 2026-02-26 20:36:02 +07:00
parent b506d97c06
commit b22f400534
3 changed files with 38 additions and 23 deletions

View File

@ -16,8 +16,8 @@ import ReportHeader from '@/views/dashboards/daily-report/report-header'
import React, { useEffect, useRef, useState } from 'react' import React, { useEffect, useRef, useState } from 'react'
// Dummy HPP values — ganti dengan data real nantinya // Dummy HPP values — ganti dengan data real nantinya
const DUMMY_STD_HPP = 30 // 30% const DUMMY_STD_HPP = 0 // % — ganti dengan data real nantinya
const DUMMY_REAL_HPP = 28 // 28% const DUMMY_REAL_HPP = 0 // % — ganti dengan kalkulasi real nantinya
const getHppStatus = (stdHpp: number, realHpp: number): 'Sehat' | 'Tidak Sehat' => const getHppStatus = (stdHpp: number, realHpp: number): 'Sehat' | 'Tidak Sehat' =>
realHpp <= stdHpp ? 'Sehat' : 'Tidak Sehat' realHpp <= stdHpp ? 'Sehat' : 'Tidak Sehat'
@ -276,7 +276,7 @@ const DailyPOSReport = () => {
</span> </span>
</div> </div>
<div className='flex justify-between items-center py-3 border-b border-gray-200'> <div className='flex justify-between items-center py-3 border-b border-gray-200'>
<span className='text-xl text-gray-700'>Biaya Layanan</span> <span className='text-xl text-gray-700'>Service Charge</span>
<span className='text-xl font-semibold text-gray-800'>{formatCurrency(0)}</span> <span className='text-xl font-semibold text-gray-800'>{formatCurrency(0)}</span>
</div> </div>
<div className='flex justify-between items-center py-3 border-b-2 border-gray-300'> <div className='flex justify-between items-center py-3 border-b-2 border-gray-300'>

View File

@ -115,8 +115,8 @@ const getStatusStyle = (status: 'Sehat' | 'Tidak Sehat', isAlt: boolean): Partia
} }
// Dummy HPP values — ganti dengan data real nantinya // Dummy HPP values — ganti dengan data real nantinya
const DUMMY_STD_HPP = 0.3 // 30% const DUMMY_STD_HPP = 0 // 0% — ganti dengan data real nantinya
const DUMMY_REAL_HPP = 0.28 // 28% const DUMMY_REAL_HPP = 0 // 0% — ganti dengan kalkulasi real nantinya
const getDummyStatus = (stdHpp: number, realHpp: number): 'Sehat' | 'Tidak Sehat' => const getDummyStatus = (stdHpp: number, realHpp: number): 'Sehat' | 'Tidak Sehat' =>
realHpp <= stdHpp ? 'Sehat' : 'Tidak Sehat' realHpp <= stdHpp ? 'Sehat' : 'Tidak Sehat'
@ -183,7 +183,7 @@ export const generateExcel = async (params: ExcelGeneratorParams) => {
['Total Diskon', profitLoss?.summary.total_discount || 0], ['Total Diskon', profitLoss?.summary.total_discount || 0],
['Total Pajak', profitLoss?.summary.total_tax || 0], ['Total Pajak', profitLoss?.summary.total_tax || 0],
['PB1', 0], ['PB1', 0],
['Biaya Layanan', 0] ['Service Charge', profitLoss?.summary.service_charge || 0]
] ]
summaryData.forEach((row, idx) => { summaryData.forEach((row, idx) => {

View File

@ -119,7 +119,7 @@ export const generatePDF = async (params: PDFGeneratorParams) => {
['Total Penjualan', formatCurrency(profitLoss?.summary.total_revenue ?? 0)], ['Total Penjualan', formatCurrency(profitLoss?.summary.total_revenue ?? 0)],
['Total Diskon', formatCurrency(profitLoss?.summary.total_discount ?? 0)], ['Total Diskon', formatCurrency(profitLoss?.summary.total_discount ?? 0)],
['Total Pajak', formatCurrency(profitLoss?.summary.total_tax ?? 0)], ['Total Pajak', formatCurrency(profitLoss?.summary.total_tax ?? 0)],
['Biaya Layanan', formatCurrency(0)], ['Service Charge', formatCurrency(profitLoss?.summary.service_charge ?? 0)],
['Total', formatCurrency(profitLoss?.summary.total_revenue ?? 0)] ['Total', formatCurrency(profitLoss?.summary.total_revenue ?? 0)]
], ],
theme: 'grid', theme: 'grid',
@ -238,12 +238,12 @@ export const generatePDF = async (params: PDFGeneratorParams) => {
pdf.text('Ringkasan Kategori', 14, currentY) pdf.text('Ringkasan Kategori', 14, currentY)
currentY += 15 currentY += 15
const DUMMY_STD_HPP = 30 // % (nilai dummy — ganti dengan data real nantinya) const DUMMY_STD_HPP = 0 // % (nilai dummy — ganti dengan data real nantinya)
const categoryBody = const categoryBody =
category?.data?.map((c: any) => { category?.data?.map((c: any) => {
const stdHpp = DUMMY_STD_HPP const stdHpp = DUMMY_STD_HPP
const realisasiHpp = 28 // dummy — ganti dengan kalkulasi real const realisasiHpp = 0 // dummy — ganti dengan kalkulasi real
const status = realisasiHpp <= stdHpp ? 'Sehat' : 'Tidak Sehat' const status = realisasiHpp <= stdHpp ? 'Sehat' : 'Tidak Sehat'
return [ return [
c.category_name, c.category_name,
@ -251,10 +251,17 @@ export const generatePDF = async (params: PDFGeneratorParams) => {
formatCurrency(c.total_revenue), formatCurrency(c.total_revenue),
`${stdHpp}%`, `${stdHpp}%`,
`${realisasiHpp}%`, `${realisasiHpp}%`,
status '' // dikosongkan — status digambar manual via didDrawCell agar tidak double
] ]
}) || [] }) || []
// Simpan status per baris untuk dipakai di didDrawCell
const categoryStatuses: string[] =
category?.data?.map(() => {
const realisasiHpp = 0
return realisasiHpp <= DUMMY_STD_HPP ? 'Sehat' : 'Tidak Sehat'
}) || []
autoTable(pdf, { autoTable(pdf, {
startY: currentY, startY: currentY,
head: [['Nama', 'Qty', 'Pendapatan', '% Std HPP', '% Real HPP', 'Status']], head: [['Nama', 'Qty', 'Pendapatan', '% Std HPP', '% Real HPP', 'Status']],
@ -308,17 +315,19 @@ export const generatePDF = async (params: PDFGeneratorParams) => {
else if (data.column.index === 1) data.cell.styles.halign = 'center' else if (data.column.index === 1) data.cell.styles.halign = 'center'
else if (data.column.index === 2) data.cell.styles.halign = 'right' else if (data.column.index === 2) data.cell.styles.halign = 'right'
} }
// Paksa teks status tidak dirender oleh autoTable (set textColor = white)
if (data.section === 'body' && data.column.index === 5) {
data.cell.styles.textColor = [255, 255, 255]
}
}, },
didDrawCell: (data: any) => { didDrawCell: (data: any) => {
// Warna teks Status (kolom index 5)
if (data.section === 'body' && data.column.index === 5) { if (data.section === 'body' && data.column.index === 5) {
const status = data.cell.text[0] const status = categoryStatuses[data.row.index] || 'Sehat'
const color = getStatusColor(status) const color = getStatusColor(status)
pdf.setTextColor(...color) pdf.setTextColor(...color)
pdf.setFontSize(9) pdf.setFontSize(9)
pdf.setFont('helvetica', 'bold') pdf.setFont('helvetica', 'bold')
pdf.text(status, data.cell.x + data.cell.width / 2, data.cell.y + data.cell.height / 2 + 1, { align: 'center' }) pdf.text(status, data.cell.x + data.cell.width / 2, data.cell.y + data.cell.height / 2 + 1, { align: 'center' })
// Reset warna
pdf.setTextColor(0, 0, 0) pdf.setTextColor(0, 0, 0)
pdf.setFont('helvetica', 'normal') pdf.setFont('helvetica', 'normal')
} }
@ -369,19 +378,21 @@ export const generatePDF = async (params: PDFGeneratorParams) => {
// Kolom baru: % Standard HPP, % Realisasi HPP, Status — dummy visual // Kolom baru: % Standard HPP, % Realisasi HPP, Status — dummy visual
const productBody = categoryProducts.map((item: any) => { const productBody = categoryProducts.map((item: any) => {
const stdHpp = 30 // dummy — ganti dengan data real const stdHpp = 0 // dummy — ganti dengan data real
const realisasiHpp = 28 // dummy — ganti dengan kalkulasi real const realisasiHpp = 0 // dummy — ganti dengan kalkulasi real
const status = realisasiHpp <= stdHpp ? 'Sehat' : 'Tidak Sehat'
return [ return [
item.product_name, item.product_name,
String(item.quantity_sold), String(item.quantity_sold),
formatCurrency(item.revenue), formatCurrency(item.revenue),
`${stdHpp}%`, `${stdHpp}%`,
`${realisasiHpp}%`, `${realisasiHpp}%`,
status '' // dikosongkan — status digambar manual via didDrawCell agar tidak double
] ]
}) })
// Status per baris produk
const productStatuses: string[] = categoryProducts.map(() => (0 <= 0 ? 'Sehat' : 'Tidak Sehat'))
const estimatedHeight = (productBody.length + 3) * 12 const estimatedHeight = (productBody.length + 3) * 12
if (currentY + estimatedHeight > 270) { if (currentY + estimatedHeight > 270) {
pdf.addPage() pdf.addPage()
@ -426,9 +437,9 @@ export const generatePDF = async (params: PDFGeneratorParams) => {
lineWidth: 0.1 lineWidth: 0.1
}, },
columnStyles: { columnStyles: {
0: { cellWidth: 55 }, 0: { cellWidth: 50 },
1: { halign: 'center', cellWidth: 20 }, 1: { halign: 'center', cellWidth: 20 },
2: { halign: 'right', cellWidth: 35 }, 2: { halign: 'right', cellWidth: 42 },
3: { halign: 'center', cellWidth: 22 }, 3: { halign: 'center', cellWidth: 22 },
4: { halign: 'center', cellWidth: 22 }, 4: { halign: 'center', cellWidth: 22 },
5: { halign: 'center', cellWidth: 22 } 5: { halign: 'center', cellWidth: 22 }
@ -439,11 +450,15 @@ export const generatePDF = async (params: PDFGeneratorParams) => {
else if (data.column.index === 1) data.cell.styles.halign = 'center' else if (data.column.index === 1) data.cell.styles.halign = 'center'
else if (data.column.index === 2) data.cell.styles.halign = 'right' else if (data.column.index === 2) data.cell.styles.halign = 'right'
} }
// Paksa teks status tidak dirender oleh autoTable (set textColor = white)
if (data.section === 'body' && data.column.index === 5) {
data.cell.styles.textColor = [255, 255, 255]
}
}, },
didDrawCell: (data: any) => { didDrawCell: (data: any) => {
// Warna teks Status (kolom index 5) // Warna teks Status (kolom index 5) — ambil dari array, bukan cell.text agar tidak double
if (data.section === 'body' && data.column.index === 5) { if (data.section === 'body' && data.column.index === 5) {
const status = data.cell.text[0] const status = productStatuses[data.row.index] || 'Sehat'
const color = getStatusColor(status) const color = getStatusColor(status)
pdf.setTextColor(...color) pdf.setTextColor(...color)
pdf.setFontSize(9) pdf.setFontSize(9)
@ -490,9 +505,9 @@ export const generatePDF = async (params: PDFGeneratorParams) => {
lineWidth: 0.2 lineWidth: 0.2
}, },
columnStyles: { columnStyles: {
0: { cellWidth: 55 }, 0: { cellWidth: 50 },
1: { halign: 'center', cellWidth: 20 }, 1: { halign: 'center', cellWidth: 20 },
2: { halign: 'right', cellWidth: 35 }, 2: { halign: 'right', cellWidth: 42 },
3: { cellWidth: 22 }, 3: { cellWidth: 22 },
4: { cellWidth: 22 }, 4: { cellWidth: 22 },
5: { cellWidth: 22 } 5: { cellWidth: 22 }