11const fs = require ( 'fs' ) ;
22const fsPromises = require ( 'fs/promises' ) ;
33const path = require ( 'path' ) ;
4+ const mongoose = require ( 'mongoose' ) ;
45
56const filename = 'BuildingUnits.json' ;
67const currentFilePath = __filename ;
@@ -9,7 +10,15 @@ const filepath = path.join(rootPath, filename);
910const { readFile } = fs ;
1011const { writeFile } = fs ;
1112
12- function bmInventoryTypeController ( InvType , MatType , ConsType , ReusType , ToolType , EquipType ) {
13+ function bmInventoryTypeController (
14+ InvType ,
15+ MatType ,
16+ ConsType ,
17+ ReusType ,
18+ ToolType ,
19+ EquipType ,
20+ invTypeHistory ,
21+ ) {
1322 async function fetchMaterialTypes ( req , res ) {
1423 try {
1524 MatType . find ( )
@@ -398,22 +407,98 @@ function bmInventoryTypeController(InvType, MatType, ConsType, ReusType, ToolTyp
398407 } ;
399408
400409 const updateNameAndUnit = async ( req , res ) => {
401- const { invtypeId } = req . params ;
402- const { name, unit } = req . body ;
403-
404410 try {
405- const updatedInvType = await InvType . findByIdAndUpdate (
406- invtypeId ,
407- { name, unit } ,
408- { new : true , runValidators : true } ,
409- ) ;
410-
411- if ( ! updatedInvType ) {
412- return res . status ( 404 ) . json ( { error : 'invType Material not found check Id' } ) ;
411+ const { invtypeId } = req . params ;
412+ const {
413+ name,
414+ unit,
415+ type : rawType ,
416+ requestor : { requestorId } ,
417+ } = req . body ;
418+ const historyDocs = [ ] ;
419+ const updateData = { } ;
420+ // Selection of Collection depending on Type
421+ const allowedTypes = [ 'Material' , 'Consumable' ] ;
422+ const itemTtype = allowedTypes . includes ( rawType ) ? rawType : 'Inventory' ;
423+
424+ // Validate invtypeId
425+ if ( ! mongoose . Types . ObjectId . isValid ( invtypeId ) ) {
426+ return res . status ( 400 ) . json ( { message : 'Invalid inventory type ID' } ) ;
427+ }
428+ // Sanitize name
429+ const safeName = String ( name ) . trim ( ) ;
430+ if ( ! safeName ) {
431+ return res . status ( 400 ) . json ( { message : 'Invalid inventory name' } ) ;
432+ }
433+ // Extract and sanitize
434+ const safeUnit = String ( unit ) . trim ( ) ;
435+ if ( ! safeUnit || safeUnit . length > 50 ) {
436+ return res . status ( 400 ) . json ( { message : 'Invalid unit value' } ) ;
437+ }
438+
439+ let CollectionName = InvType ;
440+ if ( itemTtype === 'Material' ) {
441+ CollectionName = MatType ;
442+ } else if ( itemTtype === 'Consumable' ) {
443+ CollectionName = ConsType ;
444+ }
445+
446+ // Fetch existing document
447+ const invType = await CollectionName . findById ( invtypeId ) ;
448+ if ( ! invType ) {
449+ return res . status ( 404 ) . send ( 'Inventory type not found check Id' ) ;
450+ }
451+
452+ // Perform query using sanitized values
453+ const existingInvType = await CollectionName . findOne ( {
454+ name : safeName ,
455+ _id : { $ne : mongoose . Types . ObjectId ( invtypeId ) } ,
456+ } ) ;
457+
458+ if ( existingInvType ) {
459+ return res . status ( 409 ) . json ( {
460+ message : 'Inventory type name already exists' ,
461+ } ) ;
462+ }
463+
464+ // Track name change
465+ if ( safeName && safeName !== invType . name ) {
466+ historyDocs . push ( {
467+ invtypeId,
468+ field : 'name' ,
469+ oldValue : invType . name ,
470+ newValue : safeName ,
471+ editedBy : requestorId ,
472+ } ) ;
473+ updateData . name = safeName ;
474+ }
475+
476+ // Track unit change
477+ if ( safeUnit && safeUnit !== invType . unit ) {
478+ historyDocs . push ( {
479+ invtypeId,
480+ field : 'unit' ,
481+ oldValue : invType . unit ,
482+ newValue : safeUnit ,
483+ editedBy : requestorId ,
484+ } ) ;
485+ updateData . unit = safeUnit ;
486+ }
487+
488+ // Save history (if any)
489+ if ( historyDocs . length > 0 ) {
490+ await invTypeHistory . insertMany ( historyDocs ) ;
413491 }
414492
493+ // Update main document
494+ const updatedInvType = await CollectionName . findByIdAndUpdate ( invtypeId , updateData , {
495+ new : true ,
496+ runValidators : true ,
497+ } ) ;
498+
415499 res . status ( 200 ) . json ( updatedInvType ) ;
416500 } catch ( error ) {
501+ console . error ( error ) ;
417502 res . status ( 500 ) . send ( error ) ;
418503 }
419504 } ;
@@ -638,6 +723,26 @@ function bmInventoryTypeController(InvType, MatType, ConsType, ReusType, ToolTyp
638723 }
639724 } ;
640725
726+ const fetchInvTypeHistory = async ( req , res ) => {
727+ try {
728+ const { invtypeId } = req . params ;
729+ const safeInvTypeId = new mongoose . Types . ObjectId ( invtypeId ) ;
730+ if ( ! mongoose . Types . ObjectId . isValid ( invtypeId ) ) {
731+ return res . status ( 400 ) . json ( { message : 'Invalid inventory type id' } ) ;
732+ }
733+
734+ const history = await invTypeHistory
735+ . find ( { invtypeId : safeInvTypeId } )
736+ . populate ( 'editedBy' , '_id firstName lastName email' )
737+ . sort ( { editedAt : - 1 } )
738+ . lean ( ) ;
739+
740+ res . status ( 200 ) . json ( history ) ;
741+ } catch ( error ) {
742+ console . error ( 'Fetch history error:' , error ) ;
743+ res . status ( 500 ) . json ( { message : 'Failed to fetch inventory history' } ) ;
744+ }
745+ } ;
641746 return {
642747 fetchMaterialTypes,
643748 fetchConsumableTypes,
@@ -657,6 +762,7 @@ function bmInventoryTypeController(InvType, MatType, ConsType, ReusType, ToolTyp
657762 deleteInvUnit,
658763 updateSingleInvType,
659764 deleteSingleInvType,
765+ fetchInvTypeHistory,
660766 } ;
661767}
662768
0 commit comments