update report view and remove backup files

This commit is contained in:
mahdahar 2026-03-03 09:02:34 +07:00
parent 448186bea7
commit d787522519
6 changed files with 251 additions and 110885 deletions

View File

@ -69,62 +69,70 @@
<!-- Report Content --> <!-- Report Content -->
<div x-show="!loading && selectedTest && controls.length > 0" class="space-y-6 animate-in fade-in duration-500"> <div x-show="!loading && selectedTest && controls.length > 0" class="space-y-6 animate-in fade-in duration-500">
<!-- Report Header (Print only) --> <!-- Report Header -->
<div class="hidden print:block mb-8 border-b-2 border-base-content/20 pb-4"> <div class="mb-6 print:mb-4">
<div class="flex justify-between items-end"> <!-- Main Header -->
<div class="text-center border-b-2 border-black pb-3 mb-3">
<h1 class="text-2xl font-black uppercase tracking-widest mb-1">Internal QC</h1>
<h2 class="text-lg font-bold" x-text="departmentDisplayName"></h2>
<h3 class="text-sm font-bold uppercase tracking-wide">Trisensa Diagnostic Centre</h3>
</div>
<!-- Sub Header -->
<div class="flex justify-between items-center border-b border-gray-400 pb-2">
<div> <div>
<h2 class="text-3xl font-black uppercase tracking-tighter" x-text="testName"></h2> <span class="text-xs uppercase font-bold opacity-60">Test:</span>
<p class="text-sm font-bold opacity-60" x-text="departmentName"></p> <span class="text-base font-bold ml-1" x-text="testName"></span>
</div> </div>
<div class="text-right"> <div>
<p class="text-xl font-bold" x-text="monthDisplay"></p> <span class="text-xs uppercase font-bold opacity-60">Period:</span>
<p class="text-xs opacity-50">Report Generated: <?= date('d M Y H:i') ?></p> <span class="text-base font-bold ml-1" x-text="monthDisplay"></span>
</div> </div>
</div> </div>
</div> </div>
<!-- Summary Stats --> <!-- Summary Stats - Compact Horizontal Table -->
<div class="flex flex-wrap gap-3 mb-6 no-print-gap"> <div class="mb-4 print:mb-2">
<template x-for="control in processedControls" :key="control.controlId"> <div class="bg-base-100 rounded-xl border border-base-300 shadow-sm overflow-hidden">
<div class="bg-base-100 rounded-xl border border-base-300 shadow-sm overflow-hidden flex flex-col w-full sm:w-[calc(50%-0.75rem)] lg:w-[calc(33.333%-0.75rem)] xl:w-[calc(25%-0.75rem)] print:w-[calc(33.333%-0.5rem)] print:text-[11px]"> <div class="overflow-x-auto">
<div class="bg-base-200/50 p-2 border-b border-base-300"> <table class="table table-xs w-full">
<div class="flex justify-between items-center gap-2"> <thead class="bg-base-200/50">
<h3 class="font-bold truncate text-xs" x-text="control.controlName"></h3> <tr>
<span class="badge badge-xs badge-neutral shrink-0 print:scale-75" x-text="'Lot: ' + (control.lot || 'N/A')"></span> <th class="text-left whitespace-nowrap">Control</th>
</div> <th class="text-center">Lot</th>
</div> <th class="text-center">N</th>
<div class="p-2 flex-1 grid grid-cols-2 gap-2"> <th class="text-center">Mean</th>
<div class="flex flex-col"> <th class="text-center">SD</th>
<span class="text-[9px] uppercase font-bold opacity-50">N</span> <th class="text-center">CV%</th>
<span class="text-sm font-mono font-bold" x-text="control.stats.n || 0"></span> <th class="text-center">Target</th>
</div> <th class="text-center">Bias%</th>
<div class="flex flex-col"> </tr>
<span class="text-[9px] uppercase font-bold opacity-50">Mean</span> </thead>
<span class="text-sm font-mono font-bold text-primary" <tbody>
x-text="formatNum(control.stats.mean)"></span> <template x-for="control in processedControls" :key="control.controlId">
</div> <tr class="hover:bg-base-200/30">
<div class="flex flex-col"> <td class="font-bold whitespace-nowrap" x-text="control.controlName"></td>
<span class="text-[9px] uppercase font-bold opacity-50">SD</span> <td class="text-center font-mono text-[10px]" x-text="control.lot || 'N/A'"></td>
<span class="text-sm font-mono font-bold" x-text="formatNum(control.stats.sd)"></span> <td class="text-center font-mono" x-text="control.stats.n || 0"></td>
</div> <td class="text-center font-mono" x-text="formatNum(control.stats.mean)"></td>
<div class="flex flex-col"> <td class="text-center font-mono" x-text="formatNum(control.stats.sd)"></td>
<span class="text-[9px] uppercase font-bold opacity-50">% CV</span> <td class="text-center font-mono"
<span class="text-sm font-mono font-bold" :class="control.stats.cv > 5 ? 'text-warning' : 'text-success'"
:class="control.stats.cv > 5 ? 'text-warning' : 'text-success'" x-text="formatNum(control.stats.cv, 1) + '%'"></td>
x-text="formatNum(control.stats.cv, 1) + '%'"></span> <td class="text-center font-mono text-[10px]"
</div> x-text="formatNum(control.mean) + '±' + formatNum(2*control.sd)"></td>
</div> <td class="text-center font-mono"
<div class="px-2 py-1 bg-base-200/30 text-[9px] flex justify-between border-t border-base-300 font-medium"> :class="getBiasClass(control)"
<span>Tgt: <span x-text="formatNum(control.mean)"></span>±<span x-text="formatNum(2*control.sd)"></span></span> x-text="control.stats.mean ? getBias(control) + '%' : '-'"></td>
<span x-show="control.stats.mean" :class="getBiasClass(control)" </tr>
x-text="'B: ' + getBias(control) + '%'"></span> </template>
</div> </tbody>
</table>
</div> </div>
</template> </div>
</div> </div>
<!-- Table and Chart Grid --> <!-- Table and Chart Grid -->
<div class="flex flex-col lg:flex-row gap-6"> <div class="flex gap-6">
<!-- Monthly Table (Left) --> <!-- Monthly Table (Left) -->
<div class="w-full lg:w-1/3"> <div class="w-full lg:w-1/3">
<div class="bg-base-100 rounded-xl border border-base-300 shadow-sm overflow-hidden h-full"> <div class="bg-base-100 rounded-xl border border-base-300 shadow-sm overflow-hidden h-full">
@ -132,7 +140,7 @@
<h3 class="font-bold text-sm uppercase tracking-widest opacity-70 print:text-[10px]">Daily Results Log</h3> <h3 class="font-bold text-sm uppercase tracking-widest opacity-70 print:text-[10px]">Daily Results Log</h3>
</div> </div>
<div class="overflow-x-auto max-h-[600px] overflow-y-auto"> <div class="overflow-x-auto max-h-[600px] overflow-y-auto">
<table class="table table-xs w-full print:table-xs"> <table class="table table-xs w-full">
<thead class="bg-base-200/50 sticky top-0"> <thead class="bg-base-200/50 sticky top-0">
<tr> <tr>
<th class="w-10 text-center print:px-1">Day</th> <th class="w-10 text-center print:px-1">Day</th>
@ -209,32 +217,94 @@
body { body {
-webkit-print-color-adjust: exact; -webkit-print-color-adjust: exact;
print-color-adjust: exact; print-color-adjust: exact;
color: #000 !important;
}
/* Force black and white except canvas */
* {
color: #000 !important;
border-color: #333 !important;
}
canvas, canvas * {
color: initial !important;
}
/* Force white backgrounds */
.bg-base-100, .bg-base-200, .bg-base-300, [class*="bg-base-"],
.table thead, .table tbody, .table tr, .table td, .table th {
background-color: #fff !important;
background: #fff !important;
}
/* Ensure header is visible in print */
[class*="print:mb-4"] {
display: block !important;
}
/* Header styling for print */
.border-b-2.border-black {
border-bottom: 2px solid #000 !important;
}
.border-b.border-gray-400 {
border-bottom: 1px solid #666 !important;
}
/* Compact control summary table */
.table-compact th, .table-compact td {
padding: 4px 3px !important;
font-size: 7px !important;
line-height: 1.3 !important;
border: 1px solid #ccc !important;
}
.table-compact th {
font-weight: bold !important;
background-color: #f5f5f5 !important;
}
/* Remove card styling in print */
.rounded-xl, .rounded-2xl {
border-radius: 0 !important;
}
.shadow-sm, .shadow {
box-shadow: none !important;
} }
.no-print, .no-print,
.navbar, .navbar,
footer, footer,
.drawer-side, .drawer-side,
.divider, .divider {
.mb-6:first-child,
.flex.justify-between:first-child {
display: none !important; display: none !important;
} }
.space-y-6 > div:first-child { /* Remove hiding of first child - we need the header visible */
display: none !important; /* .space-y-6 > div:first-child was hiding the header */
}
.space-y-6 > div:nth-child(2) { .space-y-6 > div:nth-child(2) {
margin-top: 0 !important; margin-top: 0 !important;
} }
html, body {
margin: 0 !important;
padding: 0 !important;
}
main { main {
padding: 0 !important; padding: 0 !important;
margin: 0 !important; margin: 0 !important;
width: 100% !important; width: 100% !important;
} }
/* Report content - natural height */
.space-y-6 {
display: block !important;
gap: 8px !important;
}
.shadow-sm, .shadow-sm,
.shadow, .shadow,
.shadow-md, .shadow-md,
@ -258,18 +328,23 @@
} }
.table-xs th, .table-xs td { .table-xs th, .table-xs td {
padding: 1px !important; padding: 4px 3px !important;
font-size: 6px !important; font-size: 7px !important;
line-height: 1.2 !important; line-height: 1.4 !important;
} }
.table { .table {
font-size: 6px !important; font-size: 7px !important;
line-height: 1.2 !important; line-height: 1.4 !important;
} }
.table tr { .table tr {
height: 15px !important; height: auto !important;
min-height: 20px !important;
}
.table tbody tr {
padding: 4px 0 !important;
} }
.overflow-x-auto { .overflow-x-auto {
@ -277,17 +352,20 @@
} }
.max-h-\[600px\] { .max-h-\[600px\] {
max-height: 500px !important; max-height: none !important;
overflow-y: visible !important;
} }
.flex-col.lg\:flex-row { /* Force 2-column layout in print */
.space-y-6 > .flex.gap-6 {
flex-direction: row !important; flex-direction: row !important;
display: flex !important; display: flex !important;
gap: 8px !important;
page-break-inside: avoid; page-break-inside: avoid;
break-inside: avoid; break-inside: avoid;
} }
.w-full.lg\:w-1\/3 { [class*="lg:w-1/3"] {
width: 35% !important; width: 35% !important;
flex: 0 0 35% !important; flex: 0 0 35% !important;
max-width: 35% !important; max-width: 35% !important;
@ -295,7 +373,7 @@
break-inside: avoid; break-inside: avoid;
} }
.w-full.lg\:w-2\/3 { [class*="lg:w-2/3"] {
width: 65% !important; width: 65% !important;
flex: 0 0 65% !important; flex: 0 0 65% !important;
max-width: 65% !important; max-width: 65% !important;
@ -327,11 +405,11 @@
gap: 2px !important; gap: 2px !important;
} }
.text-[8px] { [class*="text-[8px]"] {
font-size: 6px !important; font-size: 6px !important;
} }
.text-[9px] { [class*="text-[9px]"] {
font-size: 7px !important; font-size: 7px !important;
} }
@ -344,14 +422,20 @@
animation: none !important; animation: none !important;
} }
.h-\[560px\], /* Chart fills available height */
.h-\[560px\] canvas, .h-\[560px\] {
flex: 1 !important;
height: auto !important;
min-height: 400px !important;
}
canvas#mergedChart { canvas#mergedChart {
height: 500px !important; width: 100% !important;
height: 100% !important;
} }
.h-full { .h-full {
height: auto !important; height: 100% !important;
} }
.print\:break-inside-avoid { .print\:break-inside-avoid {
@ -363,36 +447,32 @@
padding: 2px !important; padding: 2px !important;
} }
.print\:text-\[10px\] { [class*="print:text-[10px]"] {
font-size: 8px !important; font-size: 8px !important;
} }
.print\:text-\[11px\] { [class*="print:text-[11px]"] {
font-size: 8px !important; font-size: 8px !important;
} }
.print\:scale-75 { .print\\:scale-75 {
transform: none !important; transform: none !important;
} }
.print:text-\[11px\] {
font-size: 8px !important;
}
.badge-xs { .badge-xs {
font-size: 6px !important; font-size: 6px !important;
padding: 1px 3px !important; padding: 1px 3px !important;
} }
.text-\[9px\] { [class*="text-[9px]"] {
font-size: 7px !important; font-size: 7px !important;
} }
.text-\[10px\] { [class*="text-[10px]"] {
font-size: 8px !important; font-size: 8px !important;
} }
.text-\[11px\] { [class*="text-[11px]"] {
font-size: 8px !important; font-size: 8px !important;
} }
@ -461,6 +541,29 @@
.p-2 { .p-2 {
padding: 2px !important; padding: 2px !important;
} }
/* Remove chart legend in print to save space */
.chart-legend,
.legend,
canvas + div,
[class*="legend"] {
display: none !important;
}
/* Minimize chart title area */
[class*="print:mb-1"] {
margin-bottom: 2px !important;
}
/* Ensure chart title is tiny */
[class*="print:text-[10px]"] {
font-size: 7px !important;
}
/* Remove extra padding from chart container */
.p-4.h-full {
padding: 4px !important;
}
} }
</style> </style>
<?= $this->endSection(); ?> <?= $this->endSection(); ?>
@ -589,7 +692,9 @@
const labels = days; const labels = days;
const datasets = []; const datasets = [];
let allValues = [];
// Store actual values for tooltips
const actualValues = {};
controls.forEach((control, index) => { controls.forEach((control, index) => {
const mean = parseFloat(control.mean) || 0; const mean = parseFloat(control.mean) || 0;
@ -598,19 +703,26 @@
const bgColor = bgColors[index % bgColors.length]; const bgColor = bgColors[index % bgColors.length];
const results = control.results || {}; const results = control.results || {};
const controlKey = control.controlId || index;
actualValues[controlKey] = {};
const dataPoints = days.map(day => { const dataPoints = days.map(day => {
const res = results[day]; const res = results[day];
if (res && res.resValue !== null) { if (res && res.resValue !== null && mean !== 0 && sd !== 0) {
const val = parseFloat(res.resValue); const val = parseFloat(res.resValue);
allValues.push(val); // Store actual value for tooltip
return val; actualValues[controlKey][day] = val;
// Convert to deviation from mean in SD units
return (val - mean) / sd;
} }
actualValues[controlKey][day] = null;
return null; return null;
}); });
const pointColors = dataPoints.map(v => { const pointColors = dataPoints.map(v => {
if (v === null || mean === 0 || sd === 0) return color; if (v === null) return color;
return Math.abs(v - mean) > 2 * sd ? '#ef4444' : color; // Red if outside ±2SD, otherwise use control color
return Math.abs(v) > 2 ? '#ef4444' : color;
}); });
datasets.push({ datasets.push({
@ -624,24 +736,14 @@
pointBorderColor: pointColors, pointBorderColor: pointColors,
pointHoverRadius: 6, pointHoverRadius: 6,
spanGaps: true, spanGaps: true,
tension: 0.1 tension: 0.1,
// Store reference data for tooltip
controlMean: mean,
controlSd: sd,
controlKey: controlKey
}); });
}); });
// Calculate scale
const targets = controls.map(c => parseFloat(c.mean) || 0).filter(m => m !== 0);
const sds = controls.map(c => parseFloat(c.sd) || 0).filter(s => s !== 0);
let minScale = 0, maxScale = 100;
if (allValues.length > 0 && targets.length > 0 && sds.length > 0) {
const minVal = Math.min(...allValues);
const maxVal = Math.max(...allValues);
const minTgt = Math.min(...targets) - 3.5 * Math.max(...sds);
const maxTgt = Math.max(...targets) + 3.5 * Math.max(...sds);
minScale = Math.min(minVal, minTgt);
maxScale = Math.max(maxVal, maxTgt);
}
const chartData = { const chartData = {
labels: labels, labels: labels,
datasets: datasets datasets: datasets
@ -668,26 +770,44 @@
tooltip: { tooltip: {
callbacks: { callbacks: {
label: function(context) { label: function(context) {
return context.dataset.label + ': ' + context.parsed.x; const dataset = context.dataset;
const dayIndex = context.dataIndex;
const day = days[dayIndex];
const deviation = context.parsed.x;
const actualVal = actualValues[dataset.controlKey][day];
if (actualVal === null) {
return dataset.label + ': No data';
}
const mean = dataset.controlMean;
const sd = dataset.controlSd;
return `${dataset.label}: ${actualVal.toFixed(2)} (${deviation > 0 ? '+' : ''}${deviation.toFixed(2)}σ)`;
} }
} }
} }
}, },
scales: { scales: {
x: { x: {
min: minScale, min: -3,
max: maxScale, max: 3,
title: { title: {
display: true, display: true,
text: 'Value', text: 'Deviation from Mean (SD)',
font: { size: 11, weight: 'bold' } font: { size: 11, weight: 'bold' }
}, },
grid: { grid: {
display: true, display: true,
color: '#e5e7eb' color: '#e5e7eb',
drawBorder: false
}, },
ticks: { ticks: {
font: { family: 'monospace', size: 10 } font: { family: 'monospace', size: 10 },
stepSize: 1,
callback: function(value) {
if (value === 0) return '0';
return (value > 0 ? '+' : '') + value + 'σ';
}
} }
}, },
y: { y: {
@ -705,6 +825,18 @@
stepSize: 1 stepSize: 1
} }
} }
},
annotation: {
annotations: {
line1: {
type: 'line',
xMin: 0,
xMax: 0,
borderColor: 'rgba(0,0,0,0.5)',
borderWidth: 2,
borderDash: [5, 5]
}
}
} }
}; };
@ -725,6 +857,19 @@
return test && test.deptName ? test.deptName : 'Laboratory Department'; return test && test.deptName ? test.deptName : 'Laboratory Department';
}, },
get departmentDisplayName() {
const dept = this.departmentName;
const mapping = {
'Kimia': 'Kimia Klinik',
'Imun': 'Imunologi',
'Hema': 'Hematologi',
'Mikro': 'Mikrobiologi',
'Urinal': 'Urinalisis',
'Serolo': 'Serologi'
};
return mapping[dept] || dept;
},
get monthDisplay() { get monthDisplay() {
if (!this.month) return ''; if (!this.month) return '';
const [year, month] = this.month.split('-'); const [year, month] = this.month.split('-');

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View File

@ -1,170 +0,0 @@
USE [master]
GO
/****** Object: Database [cmod_qc] Script Date: 17/01/2026 18:26:32 ******/
CREATE DATABASE [cmod_qc]
CONTAINMENT = NONE
ON PRIMARY
( NAME = N'cmod_qc', FILENAME = N'C:\db\cmod_qc.mdf' , SIZE = 8192KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
LOG ON
( NAME = N'cmod_qc_log', FILENAME = N'C:\db\cmod_qc_log.ldf' , SIZE = 32448KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
WITH CATALOG_COLLATION = DATABASE_DEFAULT, LEDGER = OFF
GO
ALTER DATABASE [cmod_qc] SET COMPATIBILITY_LEVEL = 110
GO
IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled'))
begin
EXEC [cmod_qc].[dbo].[sp_fulltext_database] @action = 'enable'
end
GO
ALTER DATABASE [cmod_qc] SET ANSI_NULL_DEFAULT OFF
GO
ALTER DATABASE [cmod_qc] SET ANSI_NULLS OFF
GO
ALTER DATABASE [cmod_qc] SET ANSI_PADDING OFF
GO
ALTER DATABASE [cmod_qc] SET ANSI_WARNINGS OFF
GO
ALTER DATABASE [cmod_qc] SET ARITHABORT OFF
GO
ALTER DATABASE [cmod_qc] SET AUTO_CLOSE OFF
GO
ALTER DATABASE [cmod_qc] SET AUTO_SHRINK OFF
GO
ALTER DATABASE [cmod_qc] SET AUTO_UPDATE_STATISTICS ON
GO
ALTER DATABASE [cmod_qc] SET CURSOR_CLOSE_ON_COMMIT OFF
GO
ALTER DATABASE [cmod_qc] SET CURSOR_DEFAULT GLOBAL
GO
ALTER DATABASE [cmod_qc] SET CONCAT_NULL_YIELDS_NULL OFF
GO
ALTER DATABASE [cmod_qc] SET NUMERIC_ROUNDABORT OFF
GO
ALTER DATABASE [cmod_qc] SET QUOTED_IDENTIFIER OFF
GO
ALTER DATABASE [cmod_qc] SET RECURSIVE_TRIGGERS OFF
GO
ALTER DATABASE [cmod_qc] SET DISABLE_BROKER
GO
ALTER DATABASE [cmod_qc] SET AUTO_UPDATE_STATISTICS_ASYNC OFF
GO
ALTER DATABASE [cmod_qc] SET DATE_CORRELATION_OPTIMIZATION OFF
GO
ALTER DATABASE [cmod_qc] SET TRUSTWORTHY OFF
GO
ALTER DATABASE [cmod_qc] SET ALLOW_SNAPSHOT_ISOLATION OFF
GO
ALTER DATABASE [cmod_qc] SET PARAMETERIZATION SIMPLE
GO
ALTER DATABASE [cmod_qc] SET READ_COMMITTED_SNAPSHOT OFF
GO
ALTER DATABASE [cmod_qc] SET HONOR_BROKER_PRIORITY OFF
GO
ALTER DATABASE [cmod_qc] SET RECOVERY SIMPLE
GO
ALTER DATABASE [cmod_qc] SET MULTI_USER
GO
ALTER DATABASE [cmod_qc] SET PAGE_VERIFY CHECKSUM
GO
ALTER DATABASE [cmod_qc] SET DB_CHAINING OFF
GO
ALTER DATABASE [cmod_qc] SET FILESTREAM( NON_TRANSACTED_ACCESS = OFF )
GO
ALTER DATABASE [cmod_qc] SET TARGET_RECOVERY_TIME = 0 SECONDS
GO
ALTER DATABASE [cmod_qc] SET DELAYED_DURABILITY = DISABLED
GO
ALTER DATABASE [cmod_qc] SET ACCELERATED_DATABASE_RECOVERY = OFF
GO
ALTER DATABASE [cmod_qc] SET QUERY_STORE = OFF
GO
USE [cmod_qc]
GO
/****** Object: Table [dbo].[CONTROL_TEST] Script Date: 17/01/2026 18:26:33 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[CONTROL_TEST](
[id] [int] IDENTITY(1,1) NOT NULL,
[controlid] [int] NULL,
[testid] [int] NULL,
[mean] [float] NULL,
[sd] [float] NULL
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[DAILY_RESULT] Script Date: 17/01/2026 18:26:33 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[DAILY_RESULT](
[id] [int] IDENTITY(1,1) NOT NULL,
[controlid] [int] NULL,
[testid] [int] NULL,
[resdate] [datetime] NULL,
[resvalue] [varchar](50) NULL,
[rescomment] [text] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
/****** Object: Table [dbo].[DICT_CONTROL] Script Date: 17/01/2026 18:26:33 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[DICT_CONTROL](
[id] [int] IDENTITY(1,1) NOT NULL,
[deptid] [int] NULL,
[name] [varchar](50) NULL,
[lot] [varchar](50) NULL,
[producer] [text] NULL,
[expdate] [date] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
/****** Object: Table [dbo].[DICT_DEPT] Script Date: 17/01/2026 18:26:33 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[DICT_DEPT](
[id] [int] IDENTITY(1,1) NOT NULL,
[name] [varchar](50) NULL,
CONSTRAINT [PK_DICT_DEPT] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[DICT_TEST] Script Date: 17/01/2026 18:26:33 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[DICT_TEST](
[id] [int] IDENTITY(1,1) NOT NULL,
[deptid] [int] NULL,
[name] [varchar](50) NULL,
[unit] [varchar](50) NULL,
[method] [varchar](50) NULL,
[cva] [varchar](50) NULL,
[ba] [varchar](50) NULL,
[tea] [varchar](50) NULL
) ON [PRIMARY]
GO
/****** Object: Table [dbo].[MONTHLY_COMMENT] Script Date: 17/01/2026 18:26:33 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[MONTHLY_COMMENT](
[id] [int] IDENTITY(1,1) NOT NULL,
[controlid] [int] NOT NULL,
[testid] [int] NOT NULL,
[commonth] [varchar](7) NOT NULL,
[comtext] [text] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
USE [master]
GO
ALTER DATABASE [cmod_qc] SET READ_WRITE
GO