Spatie Laravel ActivityLog use with differences on update and on create - laravel

I have a call to getActivitylogOptions() in a model.
But I need the data saved in the log to be different in the case of insert/update/delete.
For example, when inserting a new line, I only want to save one or two info fields. But in case of an update, I need to save all the fields that have been modified to know what exactly the user modified.
If I leave it like the following code, the update is correct, but when inserting, it saves all the fields which I don't need.
public function getActivitylogOptions(): LogOptions
{
return LogOptions::defaults()
->logAll()
->logOnlyDirty();
}
Is there any way to change the log according to the action?

Related

Custom Views for Case Records in Dynamics 365

I have a Case View which shows all the records that were created by the me (My Cases view). I now want to all those Cases edited/modified by me to be visible in that view. The problem is those modified by me could be later modified by the system when a workflow updates the Case, which changes the Modified By User data. Thus, not allowing me to use Modified By (Current User) as a condition for the view.
Is there any other way or condition which I can use to make sure the I can accomplish this?
Thank you in advance.
You may create a new Entity with One to Many relationship with Case Entity. Whenever there is Insert or Update you can add a new record in the mapping entity with Modified By Information and Created On OOB.
You can create a view in the new entity with record modified by Me.
P.S - Single case record will be edited multiple times with multiple users so it will result in high volume of data and may want to look for archiving strategy.

How to use same model with less fields for another view in mvc5

My Question is not belonging to how to use two models on same razor view ! basically I have a user table in which i have fields like(userid,name,email,password,gender,country,department,IsActive) and my form is working fine i am able to insert update and delete i have not use EF , what i did i create the table in sql server and create the model in my model folder , in my view i have put the required field validator for all these columns and they are mandatory to input while inserting or updating.
Now I want to have another view with another controller where i do not want to show all 8 fields instead want to show just these four columns( username,email,gender,IsActive)
when i am using the same model for the other controller and view then it loads the record correctly on index view ,but when i update the required it fires validation error as all my fields are mark as required so it ask to input the rest of four fields value as well.
I have tried to remove these un-necessary fields from model in controller code before saving using Bind([Exclude]"""") but it did not work.
I have tried modelstate.remove("") this approach works fine for all fields but my password field is still throwing validation error . someone says you need to use viewmodel and in viewmodel you have to put both of your model like the full model and small model, I want to ask how my small model would be mapped to my user table (as table["tableName"] this cannot be applied to two models and pointing to same table without primary foriegn key relation .
Share example please i am confused
modelState.Remove("Password")
This remove all model values which are un-necessary but not removing the password field which gives error while updating the
You have required fields missing data or some fields are not null when being saved. What you are trying to do is completely ok. You are basically using a Virtual Model. This is what I do. In the "get", you fix your model and send it to the view. You work with it and then when you submit, you receive the model in the "post", but it is missing several REQUIRED fields. So what you need to do is, retrieve the same record from the database, update the 3 or 4 fields from the view model and then save that model that you retrieved with the new data. This is one way. (VM = view model)
1. send VM to view
2. add data in the view
3. submit
4. receive VM in POST Controller
5. get same record from DB
6. update the particular fields using the VM data
7. save the updated record to database. This is the record you retrieved in 5.
Another way is to have all the missing fields in the model but not showing them in the view. However you need to mention them in the view, otherwise they will not post. so you need to use
#Html.Hidefor( x=> x.NameOfField)
This will ensure that the field is sent back for posting. Any field with a [Required]... is required. You cannot miss it!
How will your small model be mapped to the Database. It will not. You will transfer the data from the small model to the model that is mapped in the database... with ALL the fields. Either you get the missing values from the database or from the view by using Hidefor.
example
dbmodel.Field1 = vm.field1;
dbmodel.Field2 = vm.field2;
dbmodel.Field3 = vm.field3;
I hope this helps

How to display in blade which rows are soft deleted?

I have created a polling system and in the backend (CMS area) I want the ability for admins to be able to remove polls. When an admin removes a poll, it should soft delete the poll. This is working as intended, however I also want to have the ability for the admin to be able to restore a poll. To do this I am displaying all of the polls (including the soft deleted polls) in the admin area.
PollController index() to get all polls
$polls = Poll::withTrashed()->get();
In the blade I want to have two different buttons for each poll. One of restoring and one for deleting but I only want to display 1 button for each poll depending on whether it can be restored or deleted.
To do this, I have put this inside the foreach in the blade:
#if($poll->trashed())
// Restore button
#else
// Delete button
#endif
However the issue is, trashed() keeps returning true for all the polls when only 1 out of the 3 polls I have are actually soft deleted. I am unsure as to why trashed() returns all of these are true?
How would I get this method working correctly? Thanks.
PART 1
It depends on your query. When using soft deletes, Laravel will query all models that are not soft-deleted by default. When you also want to get the soft-deleted models, you need to call the withTrashed() method on your query. Read more here:
https://laravel.com/docs/5.5/eloquent#querying-soft-deleted-models
To understand what withTrashed() does, you need to understand how soft-deleting works. Soft-deleting models works by adding a new column to your database tables called deleted_at. It's value defaults to null. When you soft-delete a model, Laravel will put the current timestamp into that column. Therefore, this field doesn't contain a null value anymore.
When querying models when using soft-deletes, Laravel appends a deleted_at is null condition to the query. Calling the withTrashed() method, removes that condition from the query.
Have a look on the source of the default query modifier and the withTrashed method.
PART 2
That are events. You can call that to tell Laravel, that it should execute that specific closure when this event happens. In your example, it is listening for the "deleting" event. See more on that here:
https://laravel.com/docs/5.5/eloquent#events
PART 3
You can entirely delete soft-deletable models with the forceDelete() method. See "Permanently Deleting Models" here:
https://laravel.com/docs/5.5/eloquent#querying-soft-deleted-models
FOR EXAMPLE
$items = App\Model::withTrashed()->get();
If you want to restore a single item, just find it by ID:
$item = App\Model::find($id);

Laravel : Delete all records that are not in array

I have a datepicker calendar in my views, and basically I need to synchronize the selected dates (that I send in ajax) with a BoxDeliveryDate model (which only has one column named "date").
So in my Controller I was able to write a pretty nice method to only create a new record if one the selected dates is not yet stored in the database, like this :
foreach (Request::get('dates') as $date) {
$date_formated = date('Y-m-d', strtotime($date));
BoxDeliveryDate::firstOrCreate(['date'=>$date_formated]);
}
Now, if the user de-select one the dates in the datepicker, later, and synchronize, I need to delete it from the database.
Is there a nice way to do that in Laravel ? In other words, to delete every record of the table that are NOT in my Request::get('dates') ?
Also, I searched for a simple way to synchronize everything with only one method, but couldn't find anything.
Thanks for helping !
You can use whereNotIn() for that:
BoxDeliveryDate::whereNotIn('date', Request::get('dates'))->delete();
Note that this will not trigger any model events nor will it work with soft delete. Also, depending on the format of dates you might have to format the array before passing it to whereNotIn().
Also I believe it should be Request::input('dates') but it's possible that both actually works...
I would highly recommend using the soft delete trait (built into Laravel) if your doing mass deletes!
http://laravel.com/docs/4.2/eloquent#soft-deleting
$this->model->whereNotIn('id', $ids)->delete();

How to prevent user from modifying some fields on the form?

I am using MVC3 and EF4 to write a web application. I am using an action header like below to capture the form values submitted by the user.
<HttpPost()>
Public Function Edit(ByVal prod as Product) As ActionResult
I use the below code for updating the record.
db.Attach(prod)
db.ObjectStateManager.ChangeObjectState(prod, EntityState.Modified)
db.SaveChanges()
I get the submitted values in prod object which I update in the database. The problem is that there are some users who are not allowed to modify certain fields in a Product, say ProductCost. I have disabled the textboxes for such fields in the HTML. But since it is clientside, the user can easily enable it using some tool like Firebug and modify the value.
The only solution I could come up was to retrieve the existing record from the database and copy its ProductCost value into prod.ProductCost. But I don't like firing a query for achieving this. Is there a better way to achieve this?
Edit: I found the below link to update particular fields. How to update only one field using Entity Framework?
You can use the below code to modify a particular field.
context.ObjectStateManager.GetObjectStateEntry(user).SetModifiedProperty("FieldName");
Now the question is do I have to write the above statement for every field the user is able to modify? If yes, suppose the Product model has 10 fields (1 primary key) and the user is allowed to modify all of them except the primary key, I need to write 9 statements?? Is there a method where you can specify multiple properties at once. Or even better something where you specify the properties which are not modified. (Note: I know I can run a loop over an array of field names to avoid writing 9 statements. I am asking for an alternative method and not refactoring the above)
Never trust client data. Always have your server code to validate the input and do appropriate actions.
I would create separate overloads of my Respiratory method update the product in different ways and then check what is the current user's access type, If he is admin, i will call the overload which updates everything, if he is a manager, i will call the method which updates name,imageUrl and price and if he is an employee, i will call the method which updates only name and ImageURL
[HttpPost]
public ActionResult Edit(Product prod)
{
if(ModelState.IsValid)
{
string userType=GetCurrentUserTypeFromSomeWhere();
if(userType=="admin")
{
repo.UpdateProduct(prod);
}
else if(userType=="manager")
{
repo.UpdateProduct(prod.ID, prod.Name, prod.ImageUrl, prod.Price);
}
else if(userType=="employee")
{
repo.UpdateProduct(prod.ID, prod.Name, prod.ImageUrl);
}
return RedirectToAction("Updated",new {id=prod.ID});
}
}

Resources