imports.ts 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. 'use server';
  2. import { prisma } from '@/lib/prisma';
  3. import { revalidatePath } from 'next/cache';
  4. import { z } from 'zod';
  5. // Validation schemas
  6. const createImportSchema = z.object({
  7. name: z.string().min(1, 'Import name is required'),
  8. layoutId: z.number().int().positive('Layout configuration is required'),
  9. fileId: z.string().optional(),
  10. });
  11. const updateImportSchema = z.object({
  12. id: z.number().int().positive(),
  13. name: z.string().min(1, 'Import name is required'),
  14. fileId: z.string().optional(),
  15. });
  16. // Create a new import
  17. export async function createImport(data: {
  18. name: string;
  19. layoutId: number;
  20. fileId?: string;
  21. }) {
  22. try {
  23. const validatedData = createImportSchema.parse(data);
  24. const importRecord = await prisma.import.create({
  25. data: {
  26. name: validatedData.name,
  27. layoutId: validatedData.layoutId,
  28. importDate: new Date(),
  29. ...(validatedData.fileId && { fileId: validatedData.fileId }),
  30. },
  31. include: {
  32. layout: true,
  33. },
  34. });
  35. revalidatePath('/imports');
  36. return { success: true, data: importRecord };
  37. } catch (error) {
  38. console.error('Error creating import:', error);
  39. return { success: false, error: 'Failed to create import' };
  40. }
  41. }
  42. // Get all imports for the current user
  43. export async function getImports(userId?: string) {
  44. try {
  45. const imports = await prisma.import.findMany({
  46. where: userId ? {
  47. fileId: {
  48. not: null,
  49. },
  50. } : {},
  51. include: {
  52. layout: true,
  53. },
  54. orderBy: {
  55. importDate: 'desc',
  56. },
  57. });
  58. // Filter by userId manually since Prisma doesn't have direct relation
  59. let filteredImports = imports;
  60. if (userId) {
  61. const fileIds = await prisma.file.findMany({
  62. where: {
  63. userId: userId,
  64. },
  65. select: {
  66. id: true,
  67. },
  68. });
  69. const userFileIds = new Set(fileIds.map(f => f.id));
  70. filteredImports = imports.filter(imp =>
  71. imp.fileId && userFileIds.has(imp.fileId)
  72. );
  73. }
  74. return { success: true, data: filteredImports };
  75. } catch (error) {
  76. console.error('Error fetching imports:', error);
  77. return { success: false, error: 'Failed to fetch imports' };
  78. }
  79. }
  80. // Get a single import by ID
  81. export async function getImportById(id: number) {
  82. try {
  83. const importRecord = await prisma.import.findUnique({
  84. where: { id },
  85. include: {
  86. layout: {
  87. include: {
  88. sections: {
  89. include: {
  90. fields: true,
  91. },
  92. },
  93. },
  94. },
  95. cintasSummaries: {
  96. orderBy: {
  97. weekId: 'desc',
  98. },
  99. },
  100. },
  101. });
  102. if (!importRecord) {
  103. return { success: false, error: 'Import not found' };
  104. }
  105. return { success: true, data: importRecord };
  106. } catch (error) {
  107. console.error('Error fetching import:', error);
  108. return { success: false, error: 'Failed to fetch import' };
  109. }
  110. }
  111. // Update an import
  112. export async function updateImport(data: {
  113. id: number;
  114. name: string;
  115. fileId?: string;
  116. }) {
  117. try {
  118. const validatedData = updateImportSchema.parse(data);
  119. const importRecord = await prisma.import.update({
  120. where: { id: validatedData.id },
  121. data: {
  122. name: validatedData.name,
  123. ...(validatedData.fileId !== undefined && { fileId: validatedData.fileId }),
  124. },
  125. include: {
  126. layout: true,
  127. },
  128. });
  129. revalidatePath('/imports');
  130. return { success: true, data: importRecord };
  131. } catch (error) {
  132. console.error('Error updating import:', error);
  133. return { success: false, error: 'Failed to update import' };
  134. }
  135. }
  136. // Delete an import
  137. export async function deleteImport(id: number) {
  138. try {
  139. await prisma.import.delete({
  140. where: { id },
  141. });
  142. revalidatePath('/imports');
  143. return { success: true };
  144. } catch (error) {
  145. console.error('Error deleting import:', error);
  146. return { success: false, error: 'Failed to delete import' };
  147. }
  148. }
  149. // Calculate Cintas summaries for an import
  150. export async function calculateCintasSummaries(importId: number) {
  151. try {
  152. // This would typically call a stored procedure or perform calculations
  153. // For now, we'll simulate the calculation
  154. // In a real implementation, you might call:
  155. // await prisma.$executeRaw`CALL cintas_calculate_summary(${importId})`;
  156. // For demo purposes, we'll create some sample data
  157. const summaries = [
  158. {
  159. importId,
  160. week: '2024-W01',
  161. trrTotal: 100,
  162. fourWkAverages: 95,
  163. trrPlus4Wk: 195,
  164. powerAdds: 25,
  165. weekId: 1,
  166. },
  167. {
  168. importId,
  169. week: '2024-W02',
  170. trrTotal: 110,
  171. fourWkAverages: 100,
  172. trrPlus4Wk: 210,
  173. powerAdds: 30,
  174. weekId: 2,
  175. },
  176. ];
  177. // Clear existing summaries for this import
  178. await prisma.cintasSummary.deleteMany({
  179. where: { importId },
  180. });
  181. // Create new summaries
  182. const createdSummaries = await Promise.all(
  183. summaries.map(summary =>
  184. prisma.cintasSummary.create({
  185. data: summary,
  186. })
  187. )
  188. );
  189. return { success: true, data: createdSummaries };
  190. } catch (error) {
  191. console.error('Error calculating Cintas summaries:', error);
  192. return { success: false, error: 'Failed to calculate summaries' };
  193. }
  194. }
  195. // Get available layout configurations
  196. export async function getLayoutConfigurations() {
  197. try {
  198. const layouts = await prisma.layoutConfiguration.findMany({
  199. include: {
  200. sections: {
  201. include: {
  202. fields: true,
  203. },
  204. },
  205. },
  206. orderBy: {
  207. name: 'asc',
  208. },
  209. });
  210. return { success: true, data: layouts };
  211. } catch (error) {
  212. console.error('Error fetching layout configurations:', error);
  213. return { success: false, error: 'Failed to fetch layout configurations' };
  214. }
  215. }
  216. // Trigger import process
  217. export async function triggerImport(importId: number) {
  218. try {
  219. // Validate import exists
  220. const importRecord = await prisma.import.findUnique({
  221. where: { id: importId },
  222. include: { layout: true }
  223. });
  224. if (!importRecord) {
  225. return { success: false, error: 'Import not found' };
  226. }
  227. if (!importRecord.fileId) {
  228. return { success: false, error: 'No file attached to import' };
  229. }
  230. if (!importRecord.layout) {
  231. return { success: false, error: 'No layout configuration found' };
  232. }
  233. // Return success - the actual processing will be handled by the API endpoint
  234. return { success: true, message: 'Import process triggered successfully' };
  235. } catch (error) {
  236. console.error('Error triggering import:', error);
  237. return { success: false, error: 'Failed to trigger import' };
  238. }
  239. }