How to update foreign key from yii2-advanced curd - foreign-keys

I have created a curd using curd generation (with table status) in yii2-advanced application. and curd(create,view,edit,delete) is working properly.
Now I have created a new table relation (id, user_id, status_id) where user_id is the foreign key for user table and status_id is also foreign key for status table.
Now I want to update table relation on update status table.
For example :
1) If user test (user_id is 1) creates new status then there will be a new entry in relation table like relation (1, 1, {status_id just created by user}) .
2) if user delete status then the row with this status_id will also be removed from relation table.
3) And these created status only visible to user_id 1 only not to other users.
I am new to this framework, so please guide me how to implement this scenario in my application?
Thanks in advance.

You should add a before delete function to your model like this:
public function beforeDelete(){
if ( $this->getRelations()->count()!=0){
foreach($this->getRelations() as $relation)
{
if (Yii::$app->user->identity->id == $relation->user_id){
$relation->delete();
}
}
}
}
Also you can change AccessControl in your controller!

Related

Junction table referencing non existent entity

I have the following models in django
class WorkSession(models.Model):
pass
class Invoice(models.Model):
work_sessions = models.ManyToManyField(WorkSession, blank=True)
what I noticed is that when i do the following:
invoice = Invoice()
session = WorkSession(a=a, b=b)
invoiceo.work_sessions.set([session])
The invoice_worksession junction table gets populated with a relation, even though I haven't saved invoice yet.
Meaning that the invoices table, there's no row, but in the junction table, there's a row that references an invoice that doesn't exist yet.
Is this normal ?
Because this is causing an integrity error on fixture teardown since the invoice doesn't exist and yet, there's a refrence to
an invoice id in the junction table
EDIT
The following is a better explanation of what I'm trying to do and the problem itself
Here are my tables
CREATE TABLE "drscm_worksession" (
"id" char(32) NOT NULL,
"start_timestamp" integer NOT NULL,
"end_timestamp" integer NOT NULL,
PRIMARY KEY("id"),
);
CREATE TABLE "drscm_invoice" (
"id" char(32) NOT NULL,
PRIMARY KEY("id"),
);
and the junction table
CREATE TABLE "drscm_invoice_work_sessions" (
"id" integer NOT NULL,
"invoice_id" char(32) NOT NULL,
"worksession_id" char(32) NOT NULL,
PRIMARY KEY("id" AUTOINCREMENT),
FOREIGN KEY("invoice_id") REFERENCES "drscm_invoice"("id") DEFERRABLE INITIALLY DEFERRED,
FOREIGN KEY("worksession_id") REFERENCES "drscm_worksession"("id") DEFERRABLE INITIALLY DEFERRED
);
The objective is to create an invoice in the database with work_sessions via an api call.
The data i would need to send over, using my api client is this:
{work_sessions: [uuid1, uuid2] }
so the code would be
url = "/invoices/"
ws1 = WorkSession().save()
ws2 = WorkSession().save()
data = {'work_sessions': [ws1.id, ws2.id] }
self.client.post(path=url, data=data)
This works PERFECTLY.
BUT,
I thought, I don't want to have to write these objects manually as they get bigger in the real test.
So the approach was to do this:
invoice = Invoice()
invoice.work_sessions.set([ws1, ws2])
data = InvoiceSerializer(instance=invoice).data
self.client.post(path=url, data=data)
This does create the invoice with the according sessions BUT throws an IntegrityError exception during the teardown phase of the test
Here's why it throws the exception:
Invoice() creates an instance of the object and that instance has an id, but the invoice is NOT in the database
invoice.work_sessions.set([ws1, ws2]) creates 2 rows in the drscm_invoice_work_sessions table (junction table), and the invoice_id column takes the id of the NOT CREATED invoice instance. ( Which is the bug here)
During teardown, it tries do delete the relations in the junction table --> looks for an invoice with id: invoice.id in the drscm_invoices table, but it doesn't exit.
--> Throws an exception
You need to save the objects first to the database, such that these have a primary key, so:
invoice = Invoice.objects.create()
session = WorkSession.objects.create(a=a, b=b)
invoice.work_sessions.add(session)

Not sure how to execute complex Query with Django

I'm stuck on a query I'm trying to execute. I have attached an image of the datamodel below. Essentally, I got 6 tables with various relations. Here's a quick summary:
One User can have many Projects, and each Expense is tied to a specific project
Each project can have many users, and each user can have many projects, put together through a joined table - UserProject
To indicate the level of access a user has to a specific project, a field called role is added to the UserProject table - a user can either be a member or an admin of a project
The query I wish to construct is to fetch all expenses that are created by the logged in user (request.user) and all expenses of all projects where the user has the role of admin from the UserProject table.
See image of data model below:
Any idea how I would proceed with that query?
I think I figured it out by using Q queries
specific_project_users = Expense.objects.filter(
Q(project__projectuser__user=self.user),
Q(project__projectuser__role='admin') | Q(user=self.user)
).values("user__id")
users = User.objects.filter(id__in=specific_project_users)
Not sure how efficient the query is though.
The raw SQL query translates to this
SELECT ...
FROM "accounts_user"
WHERE "accounts_user"."id"
IN (SELECT U0."user_id"
FROM "finances_expense" U0
INNER JOIN "project" U1
ON (U0."project_id" = U1."id")
INNER JOIN "projectuser" U2 ON (U1."id" = U2."project_id")
WHERE (U2."user_id" = 1 AND (U2."role" = admin OR U0."user_id" = 1)))

Symfony2 DQL Update query with Many to Many

I have three tables "category", "product" and "product_category".
First two tables are created from two entity Category and Product.
Third table "product_category" is auto generated by framework doctrine console command.
Now I can get (fetch) product relational data (based on category id) from below query, which is fine.
$this->createQueryBuilder('p')
->leftJoin('p.category', 'c')
->select('p')
->where('c.id = :category_id')
->setParameter('category_id', 2)
->getQuery()->getSQL();
But how can I use Many-to-Many relation to Update Data?
I had Tried with several queries but its not working!!!
( I want to update all product status to inactive (2), whose category status is (2 = Inactive).
When doing a query on a table that has children. You can also just fetch the parent item, and doctrine will automatically handle the child objects. If you have a getCategory within the Product entity, it will resolve the category automatically.
Probably what you are looking for is cascading of events. of which is explained within Doctrine 2 ManyToMany cascade

Laravel 5 checkout form insert foreign key into transaction table

Right now i'm study a flow of ecommerce site using laravel 5.0 and crinsane laravel package .
I have setup 2 tables
Which is transactions and orders table
The relations is orders has many transactions (1 transaction 1 type of item ) , and transactions belong to orders .
So , in transactions there is foreign key order_id which references to order tables id .
In routes I set route::post('checkout','OrderController#checkoutpost');
public function checkoutpost()
{
// Get input from checkout forms
$input = Request::all();
// Insert forms data into Order table
Order::create($input);
// Retrieve the session data and inserting into Transaction table
$formid = str_random();
$cart_content = Cart::content();
foreach ($cart_content as $cart) {
$transaction = new Transaction();
$products = Product::find($cart->id);
$transaction->product_id = $cart->id;
$transaction->form_id = $formid;
$transaction->qty = $cart->qty;
$transaction->total_price = $cart->price * $cart->qty;
// Here is the problem , how to assign this transaction>order_id into our "id" that just inserted earlier ..
$transaction->order_id = $orders;
$transaction->save();
Cart::destroy();
return redirect('product/checkout');
}
}
The problem is how to assign order_id with the id of data that we just insert earlier?
Any feedback were really appreciated, thank you
Firstly, when creating the Order you need to assign the return value:
// An instance of Order is returned, so the id is accessible.
$order = Order::create($input);
Then you can use:
// Remember to make 'id' a fillable field on the Order model if you want to do it this way.
$transaction->order_id = $order->id;
Have you try this AvoRed an Laravel E commerce its almost fully featured e commerce for Laravel if you like it give it a try and let me know the feedback if you have any.
AvoRed An Laravel E commerce

Django AutoField not returning new primary_key

We've got a small problem with a Django project we're working on and our postgresql database.
The project we're working on is a site/db conversion from a PHP site to a django site. So we used inspect db to generate the models from the current PHP backend.
It gave us this and we added the primary_key and unique equals True:
class Company(models.Model):
companyid = models.IntegerField(primary_key=True,unique=True)
...
...
That didn't seem to be working when we finally got to saving a new Company entry. It would return a not-null constraint error, so we migrated to an AutoField like below:
class Company(models.Model):
companyid = models.AutoField(primary_key=True)
...
...
This saves the Company entry fine but the problem is when we do
result = form.save()
We can't do
result.pk or result.companyid
to get the newly given Primary Key in the database (yet we can see that it has been given a proper companyid in the database.
We are at a loss for what is happening. Any ideas or answers would be greatly appreciated, thanks!
I just ran into the same thing, but during a django upgrade of a project with a lot of history. What a pain...
Anyway, the problem seems to result from the way django's postgresql backend gets the primary key for a newly created object: it uses pg_get_serial_sequence to resolve the sequence for a table's primary key. In my case, the id column wasn't created with a serial type, but rather with an integer, which means that my sequence isn't properly connected to the table.column.
The following is based on a table with the create statement, you'll have to adjust your table names, columns and sequence names according to your situation:
CREATE TABLE "mike_test" (
"id" integer NOT NULL PRIMARY KEY,
"somefield" varchar(30) NOT NULL UNIQUE
);
The solution if you're using postgresql 8.3 or later is pretty easy:
ALTER SEQUENCE mike_test_id_seq OWNED BY mike_test.id;
If you're using 8.1 though, things are a little muckier. I recreated my column with the following (simplest) case:
ALTER TABLE mike_test ADD COLUMN temp_id serial NOT NULL;
UPDATE mike_test SET temp_id = id;
ALTER TABLE mike_test DROP COLUMN id;
ALTER TABLE mike_test ADD COLUMN id serial NOT NULL PRIMARY KEY;
UPDATE mike_test SET id = temp_id;
ALTER TABLE mike_test DROP COLUMN temp_id;
SELECT setval('mike_test_id_seq', (SELECT MAX(id) FROM mike_test));
If your column is involved in any other constraints, you'll have even more fun with it.