Hello @Cobra
Going back to basics worked. Thanks @Cobra 
I finally solved it 
UNWIND $userdata AS user
MATCH (u:User {ID:user.ID})
// Updating properties
SET u += user
WITH u, user
// Check if car is already assigned to another user
// If car is assigned to another user a timestamp is added
OPTIONAL MATCH (cr:Car)<-[:ON]-(cal:Calendar)<-[:BOUGHT]-(us:User)
WHERE NOT EXISTS(cal.end_ts) AND NOT us.ID = user.ID AND cr.ID IN $cars
SET cal.end_ts=datetime()
WITH u
// Check if car is removed
// If user has sold his car, a timestamp is added
OPTIONAL MATCH (cr:Car)<-[:ON]-(cal:Calendar)<-[:BOUGHT]-(u)
WHERE NOT EXISTS(cal.end_ts) AND NOT cr.ID IN $cars
SET cal.end_ts=datetime()
WITH u
// Assigning car to user
OPTIONAL MATCH (c:Car)
WHERE c.ID IN $cars
WITH c, u
OPTIONAL MATCH (c)<-[:ON]-(cal:Calendar)<-[:BOUGHT]-(u)
with c, u, collect(EXISTS(cal.end_ts)) AS bool, count(deploy) AS numcalnode
WITH all(x in bool where x = true) as tester, numcalnode, c, u
CALL apoc.do.case([
// User owns no cars
c IS NULL,
'RETURN DISTINCT u AS rdata',
// User has bought car(s)
c is NOT NULL AND numcalnode = 0,
'CREATE (c)<-[:ON]-(z:Calendar)<-[:BOUGHT]-(u)
SET z.start_ts=datetime()
RETURN DISTINCT u AS rdata',
// Car(s) that user already owns
c is NOT NULL AND numcalnode >= 1 AND tester = FALSE,
'RETURN DISTINCT u AS rdata',
// Car(s) that user has sold and now has decided to buy back
c is NOT NULL AND numcalnode >= 1 AND tester = TRUE,
'CREATE (c)<-[:ON]-(z:Calendar)<-[:BOUGHT]-(u)
SET z.start_ts=datetime()
RETURN DISTINCT u AS rdata'],
// Do nothing otherwise
'RETURN DISTINCT u AS rdata',
{c:c,u:u,beta:beta,test:test}) YIELD value
RETURN value as data