@@ -935,6 +935,57 @@ const FirebaseService = {
935935 console . error ( 'Users listener error:' , error ) ;
936936 } ) ;
937937 unsubscribeFunctions . push ( unsubUsers ) ;
938+
939+ // Listen to notifications for current user (rate changes, etc.)
940+ if ( AppState . currentUser ?. uid ) {
941+ // Listen to global item frequency changes to update dropdown order in real-time
942+ const unsubItemFrequency = getDb ( ) . collection ( col ( 'itemFrequency' ) ) . doc ( 'global' ) . onSnapshot ( doc => {
943+ if ( doc . exists && window . app ?. billing ) {
944+ // Update the billing manager's item frequency data
945+ window . app . billing . billingManager ?. itemFrequency &&
946+ Object . assign ( window . app . billing . billingManager . itemFrequency , doc . data ( ) ) ;
947+
948+ // Reload dropdowns to reflect new order
949+ if ( window . app . billing . loadItemsDropdown ) {
950+ window . app . billing . loadItemsDropdown ( ) ;
951+ }
952+ if ( window . app . billing . loadSaleItemsDropdown ) {
953+ window . app . billing . loadSaleItemsDropdown ( ) ;
954+ }
955+ if ( window . app . sales ?. loadItemsDropdown ) {
956+ window . app . sales . loadItemsDropdown ( ) ;
957+ }
958+ }
959+ } , error => {
960+ console . error ( 'Item frequency listener error:' , error ) ;
961+ } ) ;
962+ unsubscribeFunctions . push ( unsubItemFrequency ) ;
963+
964+ const unsubNotifications = getDb ( ) . collection ( col ( 'notifications' ) )
965+ . where ( 'userId' , '==' , AppState . currentUser . uid )
966+ . where ( 'read' , '==' , false )
967+ . orderBy ( 'timestamp' , 'desc' )
968+ . limit ( 10 )
969+ . onSnapshot ( snapshot => {
970+ snapshot . docChanges ( ) . forEach ( change => {
971+ if ( change . type === 'added' ) {
972+ const notification = change . doc . data ( ) ;
973+ // Show toast for rate change notifications
974+ if ( notification . type === 'rate_change' ) {
975+ const itemName = notification . itemHindiName || notification . itemName ;
976+ const message = `${ itemName } ${ notification . rateTypeLabel } rate: ₹${ notification . oldRate } → ₹${ notification . newRate } (by ${ notification . changedBy } )` ;
977+ UIManager . showToast ( message , 5000 ) ;
978+
979+ // Mark as read after showing
980+ getDb ( ) . collection ( col ( 'notifications' ) ) . doc ( change . doc . id ) . update ( { read : true } ) ;
981+ }
982+ }
983+ } ) ;
984+ } , error => {
985+ console . error ( 'Notifications listener error:' , error ) ;
986+ } ) ;
987+ unsubscribeFunctions . push ( unsubNotifications ) ;
988+ }
938989 } ,
939990
940991 /**
@@ -975,6 +1026,75 @@ const FirebaseService = {
9751026 }
9761027 } ,
9771028
1029+ /**
1030+ * Notifies all users when an item rate is changed.
1031+ * Creates notification documents for all users in the notifications collection.
1032+ * Note: Wholesale rate changes only notify owners/managers (staff can't see wholesale rates)
1033+ * @async
1034+ * @param {Object } item - The item with changed rate
1035+ * @param {string } rateType - Type of rate ('purchase', 'sale', 'wholesale')
1036+ * @param {number } oldRate - Previous rate value
1037+ * @param {number } newRate - New rate value
1038+ * @returns {Promise<void> }
1039+ */
1040+ async notifyRateChange ( item , rateType , oldRate , newRate ) {
1041+ try {
1042+ // Get users based on rate type
1043+ // Wholesale rates are only visible to owners/managers, so don't notify staff
1044+ let usersQuery ;
1045+ if ( rateType === 'wholesale' ) {
1046+ // Only notify owners and managers for wholesale rate changes
1047+ const ownersSnapshot = await getDb ( ) . collection ( col ( 'users' ) ) . where ( 'role' , '==' , 'owner' ) . get ( ) ;
1048+ const managersSnapshot = await getDb ( ) . collection ( col ( 'users' ) ) . where ( 'role' , '==' , 'manager' ) . get ( ) ;
1049+ const userIds = [
1050+ ...ownersSnapshot . docs . map ( doc => doc . id ) ,
1051+ ...managersSnapshot . docs . map ( doc => doc . id )
1052+ ] ;
1053+ usersQuery = { docs : userIds . map ( id => ( { id } ) ) } ;
1054+ } else {
1055+ // Notify all users for purchase and sale rate changes
1056+ usersQuery = await getDb ( ) . collection ( col ( 'users' ) ) . get ( ) ;
1057+ }
1058+
1059+ const userIds = usersQuery . docs ? usersQuery . docs . map ( doc => doc . id ) : [ ] ;
1060+
1061+ const rateTypeLabels = {
1062+ 'purchase' : 'Purchase' ,
1063+ 'sale' : 'Sale' ,
1064+ 'wholesale' : 'Wholesale'
1065+ } ;
1066+
1067+ const notification = {
1068+ type : 'rate_change' ,
1069+ itemId : item . id ,
1070+ itemName : item . name ,
1071+ itemHindiName : item . hindiName || '' ,
1072+ rateType : rateType ,
1073+ rateTypeLabel : rateTypeLabels [ rateType ] || rateType ,
1074+ oldRate : oldRate ,
1075+ newRate : newRate ,
1076+ changedBy : AppState . userName || 'Unknown' ,
1077+ changedByUserId : AppState . currentUser ?. uid ,
1078+ timestamp : firebase . firestore . FieldValue . serverTimestamp ( ) ,
1079+ read : false
1080+ } ;
1081+
1082+ // Notify all relevant users except the one who made the change
1083+ for ( const userId of userIds ) {
1084+ if ( userId !== AppState . currentUser ?. uid ) {
1085+ await getDb ( ) . collection ( col ( 'notifications' ) ) . add ( {
1086+ ...notification ,
1087+ userId : userId
1088+ } ) ;
1089+ }
1090+ }
1091+
1092+ console . log ( `Rate change notification sent: ${ item . name } ${ rateType } rate: ₹${ oldRate } → ₹${ newRate } ` ) ;
1093+ } catch ( error ) {
1094+ console . error ( 'Error notifying rate change:' , error ) ;
1095+ }
1096+ } ,
1097+
9781098 /**
9791099 * Loads withdrawals from Firestore ordered by timestamp (secondary method).
9801100 * @async
0 commit comments