You generally are not able to differentiate between a user directly making an edit to a record in the UI and some declarative or programmatic automation making an edit to a record while running in that user's context.
For example, if a user performs some action in the UI that results in a trigger firing, and that trigger updates some other record as a consequence, any subsequent automations that run based on that update cannot tell that the update was performed by the trigger as opposed to being performed directly by the user.
There's a larger issue here, and that's that your validation rule doesn't do what you want it to do. If we reformat it for clarity, it looks like this:
AND(
OR(
AND(
$Profile.Name ='Worker',
TEXT(Status)!= 'Closed',
ISCHANGED( Status )
),
AND(
$Profile.Name ='Worker',
NOT(ISCHANGED( Status )),
NOT(ISNEW())
)
),
OR(
RecordType.Name = 'NmN Record Type',
RecordType.Name = 'PHN Record Type'
)
)
Your stated objective is to allow the user with the profile 'Worker' to make no changes to the record save to move the status to Closed when it falls within the two record types you specify.
But what this validation rule does is to prevent Workers from either
- Changing the status to any value other than 'Closed', regardless of any other changes to the record.
- Changing the record without changing the Status.
So if they change the status to 'Closed', they can edit any other field on the object at the same time and your validation rule will not fire.
There's not a good way to do what you want with a validation rule. You can do it with a trigger, by looping over the fields on the new and old objects to validate the total extent of the changes. Alternately, you can override the edit function with a Visualforce or Lightning page, which would achieve your objective of enforcing this validation only for changes made through the UI, since it wouldn't affect non-UI automations.
Another option would be to completely remove Edit permission for the Worker profile, so they cannot edit it in the UI at all. Then, provide them with, for example, a Visualforce-backed button that's surfaced only on these record types and allows them to move the status to Closed, while deliberately ignoring FLS.
Best Answer
Remember that validation rules are better called invalidation rules. They tell you when data is bad, not when it's good. Don't try to construct this like you would construct an
if()
condition in Apex.At first glance, the
OR($Profile.Name <> "System Administrator", $Profile.Name <> "CSX")
should be making your spidey-senses tingle.A user can only have a single profile, so at least one of those comparisons will always return true. If one is always true, then the entire
OR()
is always true.That
OR()
for your profile check should be anAND()
instead. If a user is both not a sysadmin and not CSX, then there is a chance you want your rule to fire. Being a member of either one of those two profiles is sufficient to exclude that user from your rule.You could simplify a little by pulling the profile checks out of the nested
AND()
(because the outermost operation is anAND()
), but there's little harm in keeping that as is, and separating that section into its own "group" can help others read the validation rule.Alternatively, you could create and assign a Custom Permission to manage this instead of relying on profiles.