# Notification specifications




############### LAST STATE OF THIS 2020-05-15 12:56:44:
	Had gone over cases and triaged them, not super fleshed out yet how it works behind the scenes but basically 
	same as v7, object save triggers notification check which puts items into and takes them out of notify event table
	recurring job processes them
	Ideally would like to see event of interest check with cached data but need to consider how many different things would be in that, could be huge 
	since I will be adding so many new notification types and they are more complex.

	client end is a list type form also each object can notify directly on demand and all users have default notification subscription
	
	No longer templating but rather using short single text string with link back to open instead and optionally links to open report / attachment or whatever
	also no delivery days or hours fuckery anymore, all deliveries happen all the time as appropriate to the event deliver date.  If user wants that they can configure
	their device email notification settings, not our concern anymore.

	No reports are attached anymore, no need to generate a report outside of a User login session via the client!!!
	

###########################################################
BACKEND TODO / SYSTEM FOR RAVEN

IMPLEMENTATION PATH / PLAN - code as minimal a route as possible to get to working notifications end to end with minimal subset 
	first is test notification which is done as an implementation of the GeneralNotification Event type and is delivered to the current use running the test
		This will go through all potential problems or maybe trigger a troubleshoot route at teh server that checks all and reports back with any issues found
		Also needs to be localized (do the test route thing, that just makes the most sense.  The test route should accept the type of notification i.e. inapp or smtp, act accordingly if it's a customer user vs regular if there is any difference)
		Should report to user exactly any issues found at any level preventing it from happening
		Should submit as a job and await running in place like other ones so that its actually working end to end with the generator	
			OR
		should it submit and send immediately bypassing generator as just an immediate test.
		 OR 
		 maybe it's an option for the user to choose.

	widget / user crud ops and tag filtered in both App and in smtp
	Then viewed in UI and worked with, properly shows count waiting etc
	Examine system, bulletproof it as much as possible from first impressions
	Make sure all controls work for 
	Once have that then can flesh out all the rest afterwards

todo: Make the notification subscription front end page
	At least enough to subscription to widget biz notifications
	with translation keys
	route needed of existing subs
	route to add sub
	route to delete sub
	ui list of subs editable and saveable as a collection?
	biz object
	do it like widgets list and widget items, list up front and edit behind
	TODO:
		Do from front end back to server
		SubscriptionList datalist needed first
			timespan ui type for grid display
		then edit form and routes can be added
			Going to need a timespan control for editing


todo: make the ops notification front end page
todo: make the biz notification page
todo: implement the Widget and User crud notification systems as per spec with an eye to replicating everywhere and allowing for specialty other types in system
	i.e. not just crud but future stuff like workorder status change etc
	also this is where the tags come into play
todo: make the job objects 
todo: should be able to send a test notification to any user from user form (or user list via Customer form) as a means of ensuring the system works
todo: sql filter at server for timespan type
TODO: Translation keys needed:
	NotifyDeliveryMethod
	NotifyEventType
	NotifyDeliveryAddress
	tags
	


todo: updating subscriptions must clear out old events and notifications if they are affected
TODO: check before any thing that might create a dupe
todo: have removed the old v7 SMTP retry deliveries for simplification
	instead, it will now act as if this is always set to true
		Probe email server first if can't contact then skip smtp delivers (same as v7 when this setting true)
		New: will make every effort to err on the side of assuming delivery happened in any issue during delivery
			This will be one way to ensure it doesn't pile on the emails because of some spurious issue that actually delivered but it seemed like it might not have
		User will be able to go into notifyevent table adn remove any items they don't want delivered in case of issue

TODO: import v7 needs to create users for each contact and set their default for deliveries of notifications based on old region and send notification setting
	Make a case for this and or implement it with this work so it doesn't get lost

CREATING NOTIFICATIONS
OBJECTS Saving an object triggers notification processing for that object:
	- in v7 biz object just submits any possible notification and later it's checked to see if anyone subscribes
		would be better to short circuit that at the biz object to stop if no events of interest
	- TODO: Every corebiz object needs at least to support created / updated with tag type as a minimum
	- type and id is submitted to eventofinterest checker (possibly also tags I think)
		AyaType, ID, eventlist,objectbefore,objectafter
		eventofinterest db table contains each type and event id
			some types are generic and apply to all corebiz for example
				i.e. tags used on an object or added
		but a workorder object would be best suited to check if a workorder is interesting event?
		monolithic class for all notifications goes through a giant switch?
	- HASH to prevent dupes
		hash all the relevant bits of a notification that make it unique then check the db table to see if that hash exists already, this is a fast way to prevent dupes
			should notify if this happens a lot maybe?
		Post delivery maybe keep a hash of the event notified on so it doesn't re-notify the exact same thing repeatedly after it was already sent
	- SUBSCRIPTION
		All users have an implied / assumed default subscription InApp to default notifications
		User's indicate subscription with record in subscription table
			Table has one row PER delivery method they want, default is APP type delivery meaning inside application
			SMTP is alternative and will deliver via email to email account or phone sms etc
			FUTURE may have alternatives here
			DUPES are ignored 
		This table is consulted for all decisions about notifications, no more eventofinterest separate table nor subscriber
		DUPES - there can be near dupes here because user may have multiple of identical but vary in only:
			Delivery method
			advancenoticetimespan (e.g. contract expiring could be one 90 days in advance to renegotiate and then one 10 days in advance for notify service to cancel etc)
			tags - notify applies if has these tags
				empty means any
			s - notify cancelled if has these tags
				empty means any
				out trumps an in, default is safer option

		CONDITION
			has optional condition fields (in v7 was guidvalue for wo status type, but we need more [investigate?])
	- DELIVERY METHODS
		no more date ranges for delivery windows
		Two methods initially
			SMTP
			APP (meaning in notifications system inside application basically the old POPUP)

UI TODO
	Subscription form for user
	Subscription form for client (personal or set by administrator, probably set by administrator)
		Mass set for many users at once


V8 TABLES / OBJECTS
JOBS
	NotifySweeper
		APP notifications - deletes all APP notifications older than 90 days (if they want to keep it then can turn it into a reminder or SAVE it somehow)
		NotifyEvent - 
			deletes any notifyevent with no event date created more than 90 days ago
			If has event date and it's passed then deletes it if created more than 90 days ago (pretty sure there are no back dated events, once it's passed it's past)
		NotifyDeliveryLog - deletes all log items older than 90 days
	Notify
		Scan the notifyevent table and deliver notifications accordingly
		
GlobalBizSettings
	Add Notification system ACTIVE bool value

GlobalOpsNotificationSettings (copy from backup settings)
	SMTP creds, return address

ALL COREBIZ
	Need CRUD check for notification events
	Need to handle check of new tags vs existing tags (delta of tags) for any notification type
	Need central common code just like biz rules check that processes notifications upon any changes
		asks notifysubscription code which notifications to process
			subscriptions code has either cached or on db lookup to see all that apply, returns an array of notifyeventtypes to be processed
		Processes each notifyeventtype that it handles or passes off to central one maybe in some cases if common code

/NotifyEventType enum
	A collection of every possible notification event in one central location (rather than the old system where each object type held it's own collection)

Translation keys for each notify event type as these will display in the UI and in sent emails etc

NotifyDeliveryMethod enum
	SMTP, INAPP  (more in future)

NotifySubscriptionBiz 
	handles checking for subscription relevancy and returning to biz object caller what types of notify events to process
	handles CRUD and biz rules for notifysubscriptions

NotifyEventBiz
	handles CRUD for notify events, called statically from all over the place
	puts events in the table, removes them, updates them
	Has no part in delivery except maybe to provide list to delivery object
	provides list for admin user to remove items if they want and to view what is in there to be processed
	
NotificationBiz
	handles CRUD for (app) Notification items displayed to user in app UI
	handles flagging as seen and deleting etc

NotifyDeliveryBiz
	handle delivery and logging to notifydeliverylog
	called by generator periodically

MailMessageDelivery
	Maybe a separate object to abstract deliving emails


/notifysubscription table - contains all user (and customer user) subscriptions to events and delivery method, if user wants two delivery 
methods they have two entries here, no other table indicates events to be tracked, has user id
	also ayatype must be specific not GLOBAL to avoid a "sorcerers apprentice" runaway issue and many role related issues potentially
		so for example a CreatedWithTag notification or UpdatedWithTag notification will work on any object with that tag if a specific type i.e. customer with that tag
	Then they can control by tag as well, tags are used to filter and include (or any if no tags), s filter out and trump tags
		These are also used for tag type conditions
	(aID, userId, ayatype, aEventType, advancenoticetimespan, agevalue, idvalue, decvalue, aDeliveryMethod, deliveryaddress, linkreportid, tags, s, HASH) 

/Notifyevent table - contains all events, created by updating objects or directly in some cases and used by generator for processing as deliveries
	created (timestamp used to clean out old stuck events), ayatype, objectid, eventtype, appliestouserid (single subscriber event), aEventDate, ASAVEDMESSAGE, HASH?

notifydeliverylog table - intended for troubleshooting, logs deliveries with a cap on how many records it retains.  Keeping this as a separate and distinct OPS ui thing
	(ayatype, objectID, aEventType, aGuidValue, aDeliveryDate, aToUserID, aDeliveryMethod, aDelivered, aErrorMessage, aToClientID, HASH )

/notification table - was popup, now the ones that show in the APP type notify delivery in the UI list; has fields for opening source and reading message and indicating read
	Note: deliberately no delivery date, if it's in this table it's delivered to user, advancenotice and genprocess handle whether it's in this table or not
	eventtype should generally be enough for message but the "message" field contains any extra info
	COLUMNS: id, userid, ayatype, objectid, eventtype (for message in ui), message

###########################################################


Important cases:
client viewing ui (was popup in v7)	https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/3783



ALL EVENT TYPES INITIAL RELEASE
================================


## OLD
WorkOrderStatusChange [GENERAL] [CONDITION: WOSTATUS integer]
ContractExpiring (User notify, add more notify before time frames in cases) [GENERAL]
CSRAccepted [CUSTOMER]
CSRRejected [CUSTOMER]
NewWorkorder [CUSTOMER]
WorkorderStatusChange [CUSTOMER]  [CONDITION: WOSTATUS integer]
### DEPRECATED, WOSTATUS "Finished" status type event now replaces this ### WorkorderClosed [CUSTOMER]
### HOLD for v.next lots of cases around customer satisfaction survey etc not initial release though WorkorderFollowUp [CUSTOMER]######
QuoteStatusChanged [CUSTOMER]  [CONDITION: QUOTESTATUS integer]
ServiceBank[Currency/Hours/Incidents]Depleted [GENERAL]
NewCSR [GENERAL]
NewMemo [PERSONAL]
QuickNotification DEPRECATED replaced by GeneralNotification below [PERSONAL]
QuoteCreatedUpdated - a bit weird, which is it created or updated? :) [GENERAL]
ScheduleMarkerImminent (now "reminder") [PERSONAL]
ScheduleMarkerCreated (now "reminder") [PERSONAL]
WorkorderItemScheduledUserCreatedUpdated [PERSONAL]
WorkorderItemScheduledUserEventImminent [PERSONAL]
### CHANGED same concept but uses a COMPLETED type status as the trigger, so I guess it's WorkorderPastCompletionDate or something### WorkorderCloseByDatePassed (user) [general]
WorkorderStatusChanged (user) [GENERAL]  [CONDITION: WOSTATUS integer]
WorkorderItemOutsideServiceOverdue [general]
WorkorderItemOutsideServiceReceivedBack [GENERAL]
WorkorderItemPartRequestPartsReceived [GENERAL]


## NEW
DEADMAN_Job_procesor_fail direct email and other notifications?
	Not sure how this could work to be honest, it would need to have a generator to do the checking unless we're talking about another timer somewhere else
Daily_Notify_health_check (biz and ops) [GENERAL] CREATED BY NOTIFY DELIVERY PROCESSOR
Nightly_Notify_health_check (biz and ops)[GENERAL] created by notify delivery processor
BackupStatus case 3786 (biz and ops)	[GENERAL]	
	(OR is this more of a general OPERATIONS notifications without choosing specific type because anyone in ops needs all)
UpcomingServiceEvent case 3725 [CUSTOMER]
WorkorderItemPartRequestCreated case 3652 [GENERAL]
ContractExpiring - Customer version in addition to User version [CUSTOMER]
WorkorderTotalExceedsThreshold - Custom notification case 1745 "the andy" [GENERAL]  [CONDITION: DOLLARTOTAL money value]
WorkOrderStatusAge "deadman" delivery if *SPECIFIC* status not changed to different status before XX time period [GENERAL] [CONDITION: AGEVALUE]
https://rockfish.ayanova.com/default.htm#!/rfcaseEdit/1137
	NOTE: this will need a timespan with a different title

QuoteStatusAge [PERSONAL (prepared by), GENERAL] [CONDITION: AGEVALUE]
UnitWarranyExpiry case 1361 [GENERAL]
UnitMeterReadingMultipleExceeded case 1254 [GENERAL]
GeneralNotification case 3792 used for all system and old Quick notifications [EVERYONE]
	Always present for inapp, user can add more for email if they want and filters or whatever but there is always a built in non-visible subscription to inapp for this

deprecated, use objectCRUD events for this: TagNotification case 3799  [CONDITION: tag, , ayatype global/specific]
	(Note: this is actually just general notification if an object is created or updated and the tagging is optional)

CRUD Notifications:
	(note: tag filterable and select type specifically. Global is not a valid type for this to avoid issues)
	(note: 
	
	### WHAT DOES THIS MEAN?:differs from tag notification above in that only applies on a CHANGE of TAGS, this is an always for this op and tags are just an optional filter)

	[CONDITION: tag, , ayatype specific]
	ObjectCreated 
	ObjectUpdated
	ObjectDeleted
	ObjectAge since creation (this will cover a shitload of use cases, for example workorder follow up could be done this way etc) [CONDITION: AGEVALUE]

PERSONAL?  OR COVERED BY TAG FILTER ALREADY BETTER?
	WorkorderItemPartRequestPartsReceivedWhenIAmScheduled [PERSONAL]
	WorkorderItemOutsideServiceReceivedBackWhenIAmScheduled
	WorkorderItemOutsideServiceOverdueWhenIAmScheduled
	WorkorderCloseByDatePassedWhenIAmScheduled
	WorkorderStatusChangedWhenIAmScheduled [PERSONAL]


Not for certain but in the hopper to think about:
On demand ad-hoc notification case 3466 for specific object only
	not sure how to handle that, but it's a very intruiging idea, maybe it's a v.next one though?
	or maybe the tags thing will handle this?


CUSTOMER NOTIFICATIONS AND CHANGES
A bcc field for all customer notification subscriptions per case 3398

SCRATCHPAD IDEAS
=-=-=-=-=-=-=-=-=-

OVERVIEW
General
	thinking of reforming it, making all notifications very short since user can go to directly view data online anyway now, why have an overly time consuming system to format and shit
	i.e. no notification more than an SMS (160 characters but will accept more and split them up to 1600) tweet in length (280 characters)

	In cases where user wants to send a link to an attachment / report / wiki that's another thing entirely but the message is still super short

	All notifications can be optionally filtered IN or OUT via tags on notification related object.  I.E. a workorder status change can be ignored or only see if it's tagged "region-new-york" etc

	All users can receive general notifications which come from both the system itself and from other users using the new ad-hoc send notification from any form

UI
Subscribe from the object itself's menu rather than centralized subscription setup (new)
Admin can still subscribe users on their behalf (new)

SYSTEM
-=-=-=-=-=-=-=-=-=-
EVENT_OF_INTEREST_CLASS

Internal workings:
	
	Should cache the event of interest for quick saving processing and save db getting hammered every time an object is saved



One enum list of NotificationType for any possible notification that can be processed
	Notify type is divided by actual type and then by actual delivery method
No delivery schedule anymore, let user decide how to handle at their device end, not our concern, just deliver immediately always
Notify BEfore shoudl support multiple time frames, not just one
Users not involved should not be notified, have choice on that`
	e.g. if a user is not booked on a workorder and is just a lowly tech they don't care about other workorder status changes


Types of notifications sitting in delivery queue:
	Deliver if something not changed before date "DEADMAN SWITCH"
		upon change that negates it from source object it removes the event as no longer required
	Deliver immediately regardless
		easy peasy

	





DELIVERY TYPES
	Email
	UI
	(previusly was ayanova memo, but, that's toast now, removing it)
DELIVERY FORMAT
	Custom templates for each notification set up centrally?



Hypothetical sequence of operations for designing raven notification and tie into jobs and processor

WidgetStatusChange notification
	- OnChange event triggered in [WIDGETBIZ] with before and after state of widget in question (immediately after save or delete or whatever is of interest)	
		- OnChange processor See if any users are subscribed to this event [CENTRAL_NOTIFICATION_CLASS THIS MUST BE SUPER EFFICIENT AS IT WILL BE HAMMERED] 
		(events of interest / core central event bus handler of some kind??)
			- CENTRAL_NOTIFICATION_CLASS event of interest should cache in memory events of interest and trigger cache invalidation by [EVENT_OF_INTEREST_CLASS] subscription change
		- If no then bail out early
		- If yes then compares the before and after state of the widget and the given list of events of interest and processes notifications in turn
			- Create a notification event in a table of pending notification events [CENTRAL_NOTIFICATION_CLASS]
				- See v7 schema for ideas

Deliver notifications
	- Job triggers and HandleJob is called on [CENTRAL_NOTIFICATION_CLASS] which in turn checks if any events ready to Deliver
		- Hands off NOTIFY_EVENT to deliver one at a time to a [NOTIFICATION_DELIVERY_CLASS] which in turn calls each [NOTIFICATION_DELIVERY_DELIVERY_TYPE-SMTP/POPUP/WHATEVER]


Maintenance
	- [CoreJobNotificationSweeper class] maintains the notifications tables see generator spec for thoughts









- What is "Slack"?
	- should we tie into it for notifications?