Allow atomic update to the database - yii

Given several model classes like
car, supplier, ...
we have save() method for each of them.
What i want to achieve is that, i want to save
car and supplier
models, and if one of models failed, none are saved.
Is there a way to achieve this?

You are looking for transactions. Have a look here:
http://www.yiiframework.com/doc/guide/1.1/en/database.ar#using-transaction-with-ar
$transaction=$model->dbConnection->beginTransaction();
if($car->save() && $supplier->save()) {
$transaction->commit();
} else {
$transaction->rollback();
}

Related

Prestashop Module: hooks and orders

I am having multiple questions about this topic
As the title states, I am in need to find the correct hook to bind when an order has been placed and the payment was accepted.
1.) Which hook should I bind in my module when an order has been placed (and payed)?
2.) I am under the impression that there is no generalized hook for this, since some payment methods set the order status to 'payed' automatically (like a successful PayPal transaction) while other methodes require the shopowner to manually set the status to 'payed'. Are there any more than just those two that must be called to cover most cases?
3.) Eventhough I am still hoping that there is a generalized hook, if there's none, how would I approach this issue? Bind "actionPaymentConfirmation" aswell as "displayPaymentReturn" to cover both cases?
4.) Why is the hook "actionPaymentConfirmation" never called when I set the order status to "payed" in the backoffice. My code looks like this
public function install() {
if (!parent::install() || !$this->registerHook("actionPaymentConfirmation")) {
return false;
}
return true;
}
public function actionPaymentConfirmation($params) {
print_r($params); // stepping through with XDebug but the function is never being invoked
}
5.) Does anyone know a free module doing something simmilar I can dig into to get a better idea?
6.) Or might it be easier to override Prestashops core classes to tackle my problems? To break it down, I want to execute stuff after an order has been placed and the status is set to payment was accepted or remotely accepted.
Well, I hope I am not asking to much stuff at the same time, but as you can see, I am interested in mastering these things but have some troubles along the way. Have now been trying and especially search for answers for days now without any luck.
Regards!
I assume that you're with PrestaShop 1.5
1 actionValidateOrder (for new order) & actionOrderStatusPostUpdate (here you can check about the "paid" status)
2 Like 1.
3 Like 1.
4 The hook is actionOrderStatusPostUpdate
5
public function install()
{
return (parent::install()
AND $this->registerHook('newOrder')
AND $this->registerHook('actionOrderStatusPostUpdate'));
}
public function hookNewOrder($params)
{
return $this->hookActionOrderStatusPostUpdate($params);
}
public function hookActionOrderStatusPostUpdate($params)
{
//$params['newOrderStatus'] // after status changed
//$params['orderStatus'] // after order is placed
}
6 Look at 5.
Note: actionValidateOrder the new name (alias) of newOrder

Eloquent many-to-many with filters on both sides

I've been reading the docs but I"m not sure how to do this. http://doc.laravelbook.com/eloquent/#many-to-many
Say I have a users, roles, and a pivot table.
I have belongsToMany set up for both Role and User
In a controller, I want to get a user_id and return what roles they have of a specific type only.
(There is also a role type table, but I can work with the IDs directly).
I start something like this
$specific_type_role = Role::where('role_type_id', 3)::where(?$user_id?)
//need to involve
$circle_users = RoleUser::where('user_id', $user_id)->get();
but I think it should be able to be done automatically. don't know how to include the filter right in the query.
Not sure if it's that what you need but, you probably will be able to do something like that:
public function getAdminRoles()
{
$user = User::find(1);
return $user->roles()->where('role_type_id', 1)->get();
}

ASP.NET MVC FluentValidation with ViewModels and Business Logic Validation

I'm exploring using FluentValidation as it seems to be an elegant API for validation of my ViewModels upon model binding. I'm looking for opinions on how to properly centralize validation using this library as well as from my business (service) layer and raise it up to the view without having 2 different approaches to adding modelstate errors.
I'm open to using an entirely different API but essentially looking to solve this branching validation strategy.
[Side Note: One thing I tried was to move my business method into my FluentValidation's custom RsvpViewModelValidator class and using the .Must method but it seemed wrong to hide that call in there because if I needed to actually use my Customer object they I would have to re-query it again since its out of scope]
Sample Code:
[HttpPost]
public ActionResult AcceptInvitation(RsvpViewModel model)
{
//FluentValidation has happened on my RsvpViewModel already to check that
//RsvpCode is not null or whitespace
if(ModelState.IsValid)
{
//now I want to see if that code matches a customer in my database.
//returns null if not, Customer object if existing
customer = _customerService.GetByRsvpCode(model.RsvpCode);
if(customer == null)
{
//is there a better approach to this? I don't like that I'm
//splitting up the validation but struggling up to come up with a
//better way.
ModelState.AddModelError("RsvpCode",
string.Format("No customer was found for rsvp code {0}",
model.RsvpCode);
return View(model);
}
return this.RedirectToAction(c => c.CustomerDetail());
}
//FluentValidation failed so should just display message about RsvpCode
//being required
return View(model);
}
[HttpGet]
public ActionResult CustomerDetail()
{
//do work. implementation not important for this question.
}
To give some closure to the question (and make it acceptable) as well as summarize the comments:
Business/process logic and validation logic are two entities. Unless the validation ties in to the database (e.g. check for unique entries) there's no reason to group validation into one location. Some are responsible in the model making sure there's nothing invalid about the information, and some handle how the validated values are used within the system. Think of it in terms of property getters/setters vs the logic used in the methods with those properties.
That being said, separating out the processes (checks, error handling, etc.--anything not relating to UI) can be done in a service layer which also tends to keep the application DRY. Then the action(s) is/are only responsible for calling and presenting and not performing the actual unit of work. (also, if various actions in your application use similar logic, the checks are all in one location instead of throw together between actions. (did I remember to check that there's an entry in the customer table?))
Also, by breaking it down in to layers, you're keeping concerns modular and testable. (Accepting an RSVP isn't dependent on an action in the UI, but now it's a method in the service, which could be called by this UI or maybe a mobile application as well).
As far as bubbling errors up, I usually have a base exception that transverses each layer then I can extend it depending on purpose. You could just as easily use Enums, Booleans, out parameters, or simply a Boolean (the Rsvp either was or wasn't accepted). It just depends on how finite a response the user needs to correct the problem, or maybe change the work-flow so the error isn't a problem or something that the user need correct.
You can have the whole validation logic in fluent validation:
public class RsvpViewValidator : AbstractValidator<RsvpViewModel>
{
private readonly ICustomerService _customerService = new CustomerService();
public RsvpViewValidator()
{
RuleFor(x => x.RsvpCode)
.NotEmpty()
.Must(BeAssociatedWithCustomer)
.WithMessage("No customer was found for rsvp code {0}", x => x.RsvpCode)
}
private bool BeAssociatedWithCustomer(string rsvpCode)
{
var customer = _customerService.GetByRsvpCode(rsvpCode);
return (customer == null) ? false : true;
}
}

How to perform validation against dB before NHibernate update

The following scenario is, I would say quite common and although I know one way of resolving it but it lack elegance.
The example I'm giving is based upon https://github.com/sharparchitecture/Sharp-Architecture-Cookbook.
The application I'm coding is an ASP.NET MVC application and has to support multiple users working on the same object.
The following scenario is an edge case but nevertheless a valid one.
Say you have two users working on the same object and whether the dB row can be updated depends upon the value of a particular field. To make it more concrete, let's say you have a Product and to keep things simple, this Product has "Name" and "QuantityInStock" fields.
Say that initially, there are 10 items of the Product and User1 and User2 want to buy this product. When both users are presented the initial form they are told that there are 10 of these items in stock. Now User1 buys all 10 items while User2 goes to have a coffee. So User1's transaction goes through no problem.
Then User2 comes back after his coffee in the belief that there are still 10 items in stock. So he tries to buy 1 but he must be prevented from doing so since there are no items in stock.
So this problem can be solved by using ASP.NET DataAnnotations validation and this will catch the majority of cases. However, in our edge case, say that User1 and User2 perform the same operation but within a fraction of a second such that when User2 submits the form, it passes the ASP.NET Validation but by the time it gets to the persistence layer, the QuantityInStock is 0.
The solution to this is to perform the validation at the latest moment as possible i.e. just before calling the Update method.
Now for some code.
public ProductModel CreateOrUpdate(ProductModel productModel)
{
var currentProductModel = Get(productModel.Id);
var currentQuantityInStock = currentProductModel.QuantityInStock;
if(currentProductModel.QuantityInStock !=0 && productModel.QuantityInStock >= currentQuantityInStock )
{
currentProductModel.QuantityInStock= productModel.QuantityInStock;
currentProductModel.Name = productModel.Name;
this.productModelRepository.SaveOrUpdate( currentProductModel );
return productModel;
}
else
{
//Raise an exception
}
}
Now, the fact that I'm calling:
var currentProductModel = Get(productModel.Id);
means that if I were to just do this:
this.productModelRepository.SaveOrUpdate( productModel );
would cause an exception:
a different object with the same identifier value was already associated with the session: 1
Hence, I have to copy all of the values from productModel to currentProductModel. It's fine when using something like Automapper but still kind of feels wrong to me in the sense that I feel I should just be able to save productModel as is without having to transfer the data from one object to another.
Moreover, having to do the same validation twice, once using DataAnnotation and another time just before updating violates the DRY principle.
The point is that I feel like I'm missing a trick but don't quite know where to start and what to investigate.
This to me is a simple problem but coming up with a nice elegant solution is something else. So the question is how have you dealt with this simple case in the past? Am I overthinking this?
have you tried optimistic Locking with Version?
// Fluent mapping
public EntitiyMap()
{
OptimisticLock.All(); // all properties musn't be changed in db when saving
// or
OptimisticLock.Dirty(); // only dirty properties musn't be changed in db when saving
}
//
public ProductModel CreateOrUpdate(ProductModel productModel)
{
try
{
// productModel is already validated and updated
this.productModelRepository.SaveOrUpdate( productModel );
return productModel;
}
catch (StaleObjectException)
{
// somebody changed the object in database after we have read it
// Raise an exception or whatever
}
}
Update: i handled such things in another way
public void BuySomething(ProductModel productModel, int amount)
{
int tries = 5;
bool success = false;
while(!success && tries > 0)
{
if (productModel.QuantityInStock <= amount)
{
//Raise an exception
}
productModel.QuantityInStock - amount;
try
{
this.productModelRepository.SaveOrUpdate( productModel );
}
catch (StaleObjectException)
{
// somebody changed the object in database after we have read it
this.productModelRepository.Refresh(productModel);
tries--;
}
}
if (tries <= 0)
{
// Raise an exception or whatever
}
}
zero extra roundtrips if nobody changed it in between, and guaranteed serialisation of the transactions

Where to expose the results of a specific SQL query in the domain model

Which of these examples would be the best way to expose a collection of Orders for a specific Person that contain a specific Product and why? Or maybe there is a better way to do this alltogether? (Sorry I am new to domain modeling). The Orders list is pulled from the database with an SQL query and turned into a List collection.
A Person has 1 to many Orders and an Order has 1 to many Products.
1)
class Person
{
List OrdersContaining(Product p)
{.....}
}
2)
class Order
{
List ForPersonContainingProduct(Person person, Product product)
{.....}
}
2)
class Product
{
List OrdersFor(Person p)
{.....}
}
I would not expose such a method directly on the domain object itself, which encapsulates the data. Rather, I would use the DAO pattern applied to the Order domain. Which, in essence, is a variation of your #2:
class OrderDAO {
List<Order> listByPersonAndProduct(Person person, Product product){
.....
}
}
This way, the various patterns of access that you need to add over time are separated from the Order domain object.
Person could still have a .Orders collection which has all their orders. Then it becomes a question of lazy loading an populating this collection when you know you're going to need it. Something like N/Hibernate helps a lot here.