From adc8d36bb0750c74fa77509dc713e36f521209d7 Mon Sep 17 00:00:00 2001
From: Erik Thuning <boooink@gmail.com>
Date: Tue, 23 Jul 2019 15:26:27 +0200
Subject: [PATCH] Introducing events - loans are now events, and there is also
 a service event type

---
 database.sql        |  31 +++++++------
 include/Event.php   | 104 ++++++++++++++++++++++++++++++++++++++++++++
 include/Loan.php    | 103 ++++++++++++-------------------------------
 include/Service.php | 103 +++++--------------------------------------
 4 files changed, 161 insertions(+), 180 deletions(-)
 create mode 100644 include/Event.php

diff --git a/database.sql b/database.sql
index c480b4c..0f4b552 100644
--- a/database.sql
+++ b/database.sql
@@ -75,29 +75,34 @@ create table `user` (
 ) character set utf8mb4,
   collate utf8mb4_unicode_ci;
 
-create table `loan` (
+create table `event` (
   `id` bigint(20) not null auto_increment,
   primary key(`id`),
-  `user` bigint(20) not null,
-  constraint `l_f_user`
-    foreign key(`user`) references `user`(`id`),
   `product` bigint(20) not null,
-  constraint `l_f_product`
+  constraint `e_f_product`
     foreign key(`product`) references `product`(`id`),
   `starttime` bigint(20) not null,
-  `endtime` bigint(20) not null,
   `returntime` bigint(20) default null
 ) character set utf8mb4,
   collate utf8mb4_unicode_ci;
 
+create table `loan` (
+  `event` bigint(20) not null,
+  primary key(`event`),
+  constraint `l_f_event`
+    foreign key(`event`) references `event`(`id`),
+  `user` bigint(20) not null,
+  constraint `l_f_user`
+    foreign key(`user`) references `user`(`id`),
+  `endtime` bigint(20) not null
+) character set utf8mb4,
+  collate utf8mb4_unicode_ci;
+
 create table `service` (
-  `id` bigint(20) not null auto_increment,
-  primary key(`id`),
-  `product` bigint(20) not null,
-  constraint `s_f_product`
-    foreign key(`product`) references `product`(`id`),
-  `starttime` bigint(20) not null,
-  `returntime` bigint(20) default null
+  `event` bigint(20) not null,
+  primary key(`event`),
+  constraint `s_f_event`
+    foreign key(`event`) references `event`(`id`)
 ) character set utf8mb4,
   collate utf8mb4_unicode_ci;
 
diff --git a/include/Event.php b/include/Event.php
new file mode 100644
index 0000000..a697270
--- /dev/null
+++ b/include/Event.php
@@ -0,0 +1,104 @@
+<?php
+class Event {
+    protected $id = 0;
+    protected $product = 0;
+    protected $starttime = 0;
+    protected $returntime = null;
+
+    protected static function create_event($product) {
+        $status = $product->get_status();
+        if($status != 'available') {
+            $emsg = '';
+            $prod_id = $product->get_id();
+            switch($status) {
+                case 'on_loan':
+                case 'overdue':
+                    $loan_id = $product->get_active_loan()->get_id();
+                    $emsg = "Product $prod_id has an active "
+                          . "loan (id $loan_id).";
+                    break;
+                case 'discarded':
+                    $emsg = "Product $prod_id has been discarded.";
+                    break;
+                case 'service':
+                    $service_id = $product->get_active_service()->get_id();
+                    $emsg = "Product $prod_id is on service "
+                          . "(id $service_id).";
+                    break;
+            }
+            throw new Exception($emsg);
+        }
+        $now = time();
+        $insert = prepare('insert into
+                               `event`(`product`, `starttime`)
+                               values (?, ?)');
+        bind($insert, 'ii', $product->get_id(), $now);
+        execute($insert);
+        $event_id = $insert->insert_id;
+        return new Event($event_id);
+    }
+    
+    public function __construct($id) {
+        $search = prepare('select `id` from `event`
+                           where `id`=?');
+        bind($search, 'i', $id);
+        execute($search);
+        $result = result_single($search);
+        if($result === null) {
+            throw new Exception('Event does not exist.');
+        }
+        $this->id = $result['id'];
+        $this->update_fields();
+    }
+    
+    protected function update_fields() {
+        $get = prepare('select * from `event` where `id`=?');
+        bind($get, 'i', $this->id);
+        execute($get);
+        $result = result_single($get);
+        $this->product = $result['product'];
+        $this->starttime = $result['starttime'];
+        $this->returntime = $result['returntime'];
+    }
+
+    public function get_id() {
+        return $this->id;
+    }
+
+    public function get_product() {
+        return new Product($this->product);
+    }
+
+    public function get_starttime() {
+        return $this->starttime;
+    }
+
+    public function get_returntime() {
+        return $this->returntime;
+    }
+    
+    public function is_active() {
+        if($this->returntime === null) {
+            return true;
+        }
+        return false;
+    }
+
+    public function get_status() {
+        $class = strtolower(get_class($this));
+        if($this->is_active()) {
+            return 'active_' . $class;
+        }
+        return 'inactive_' . $class;
+    }
+
+    public function end() {
+        $now = time();
+        $query = prepare('update `event` set `returntime`=? where `id`=?');
+        bind($query, 'ii', $now, $this->id);
+        execute($query);
+        $this->returntime = $now;
+        return true;
+    }
+}
+?>
diff --git a/include/Loan.php b/include/Loan.php
index 1fb4fd6..3165de7 100644
--- a/include/Loan.php
+++ b/include/Loan.php
@@ -1,111 +1,52 @@
 <?php
-class Loan {
-    private $id = 0;
+class Loan extends Event {
     private $user = 0;
-    private $product = 0;
-    private $starttime = 0;
     private $endtime = 0;
-    private $returntime = null;
 
     public static function create_loan($user, $product, $endtime) {
-        $status = $product->get_status();
-        if($status != 'available') {
-            $emsg = '';
-            $prod_id = $product->get_id();
-            switch($status) {
-                case 'on_loan':
-                case 'overdue':
-                    $loan_id = $product->get_active_loan()->get_id();
-                    $emsg = "Product $prod_id has an active ";
-                    $emsg .= "loan (id $loan_id) already.";
-                    break;
-                case 'discarded':
-                    $emsg = "Product $prod_id has been discarded.";
-                    break;
-                case 'service':
-                    $service_id = $product->get_active_service()->get_id();
-                    $emsg = "Product $prod_id is on service (id $service_id).";
-                    break;
-            }
-            throw new Exception($emsg);
-        }
-        $now = time();
-        $insert = prepare('insert into
-                               `loan`(`user`, `product`, `starttime`, `endtime`)
-                               values (?, ?, ?, ?)');
-        bind($insert, 'iiii',
-             $user->get_id(), $product->get_id(),
-             $now, strtotime($endtime . ' 13:00'));
+        begin_trans();
+        $event = parent::create_event($product);
+        $event_id = $event->get_id();
+        $insert = prepare('insert into `loan`(`user`, `endtime`) values (?, ?)');
+        bind($insert, 'ii', $user->get_id(), strtotime($endtime . ' 13:00'));
         execute($insert);
-        $loan_id = $insert->insert_id;
-        return new Loan($loan_id);
+        commit_trans();
+        return new Loan($event_id);
     }
     
     public function __construct($id) {
-        $search = prepare('select `id` from `loan`
-                           where `id`=?');
+        parent::__construct($id);
+        $search = prepare('select * from `loan` where `event`=?');
         bind($search, 'i', $id);
         execute($search);
         $result = result_single($search);
         if($result === null) {
             throw new Exception('Loan does not exist.');
         }
-        $this->id = $result['id'];
         $this->update_fields();
     }
     
-    private function update_fields() {
-        $get = prepare('select * from `loan` where `id`=?');
+    protected function update_fields() {
+        parent::update_fields();
+        $get = prepare('select * from `loan` where `event`=?');
         bind($get, 'i', $this->id);
         execute($get);
         $loan = result_single($get);
         $this->user = $loan['user'];
-        $this->product = $loan['product'];
-        $this->starttime = $loan['starttime'];
         $this->endtime = $loan['endtime'];
-        $this->returntime = $loan['returntime'];
-    }
-
-    public function get_id() {
-        return $this->id;
     }
 
     public function get_user() {
         return new User($this->user);
     }
 
-    public function get_product() {
-        return new Product($this->product);
-    }
-
-    public function get_duration($format = true) {
-        $style = function($time) {
-            return $time;
-        };
-        if($format) {
-            $style = function($time) {
-                if($time) {
-                    return gmdate('Y-m-d', $time);
-                }
-                return $time;
-            };
-        }
-        return array('start' => $style($this->starttime),
-                     'end' => $style($this->endtime),
-                     'end_renew' => $style($this->endtime + 604800), # +1 week
-                     'return' => $style($this->returntime));
-    }
-
-    public function is_active() {
-        if($this->returntime === null) {
-            return true;
-        }
-        return false;
+    public function get_endtime() {
+        return $this->endtime;
     }
 
     public function extend($time) {
         $ts = strtotime($time . ' 13:00');
-        $query = prepare('update `loan` set `endtime`=? where `id`=?');
+        $query = prepare('update `loan` set `endtime`=? where `event`=?');
         bind($query, 'ii', $ts, $this->id);
         execute($query);
         $this->endtime = $ts;
@@ -114,7 +55,7 @@ class Loan {
     
     public function end() {
         $now = time();
-        $query = prepare('update `loan` set `returntime`=? where `id`=?');
+        $query = prepare('update `event` set `returntime`=? where `id`=?');
         bind($query, 'ii', $now, $this->id);
         execute($query);
         $this->returntime = $now;
@@ -131,5 +72,15 @@ class Loan {
         }
         return false;
     }
+
+    public function get_status() {
+        if($this->is_overdue()) {
+            return 'overdue_loan';
+        }
+        if($this->is_active()) {
+            return 'active_loan';
+        }
+        return 'inactive_loan';
+    }
 }
 ?>
diff --git a/include/Service.php b/include/Service.php
index 5f19014..79f274a 100644
--- a/include/Service.php
+++ b/include/Service.php
@@ -1,109 +1,30 @@
 <?php
-class Service {
-    private $id = 0;
-    private $product = 0;
-    private $starttime = 0;
-    private $returntime = null;
-
+class Service extends Event {
     public static function create_service($product) {
-        $status = $product->get_status();
-        if($status != 'available') {
-            $emsg = '';
-            $prod_id = $product->get_id();
-            switch($status) {
-                case 'on_loan':
-                case 'overdue':
-                    $loan_id = $product->get_active_loan()->get_id();
-                    $emsg = "Product $prod_id has an active ";
-                    $emsg .= "loan (id $loan_id).";
-                    break;
-                case 'discarded':
-                    $emsg = "Product $prod_id has been discarded.";
-                    break;
-                case 'service':
-                    $service_id = $product->get_active_service()->get_id();
-                    $emsg = "Product $prod_id is on service "
-                           ."(id $service_id) already.";
-                    break;
-            }
-            throw new Exception($emsg);
-        }
-        $now = time();
-        $insert = prepare('insert into
-                               `service`(`product`, `starttime`)
-                               values (?, ?)');
-        bind($insert, 'ii', $product->get_id(), $now);
+        begin_trans();
+        $event = parent::create_event($product);
+        $event_id = $event->get_id();
+        $insert = prepare('insert into `service`(`event`) values (?)');
+        bind($insert, 'i', $event_id);
         execute($insert);
-        $service_id = $insert->insert_id;
-        return new Loan($service_id);
+        commit_trans();
+        return new Service($event_id);
     }
     
     public function __construct($id) {
-        $search = prepare('select `id` from `service`
-                           where `id`=?');
+        parent::__construct($id);
+        $search = prepare('select * from `service` where `event`=?');
         bind($search, 'i', $id);
         execute($search);
         $result = result_single($search);
         if($result === null) {
             throw new Exception('Service does not exist.');
         }
-        $this->id = $result['id'];
         $this->update_fields();
     }
-    
-    private function update_fields() {
-        $get = prepare('select * from `service` where `id`=?');
-        bind($get, 'i', $this->id);
-        execute($get);
-        $loan = result_single($get);
-        $this->product = $loan['product'];
-        $this->starttime = $loan['starttime'];
-        $this->returntime = $loan['returntime'];
-    }
 
-    public function get_id() {
-        return $this->id;
-    }
-
-    public function get_user() {
-        return 'Service';
-    }
-    
-    public function get_product() {
-        return new Product($this->product);
-    }
-
-    public function get_duration($format = true) {
-        $style = function($time) {
-            return $time;
-        };
-        if($format) {
-            $style = function($time) {
-                if($time) {
-                    return gmdate('Y-m-d', $time);
-                }
-                return $time;
-            };
-        }
-        return array('start' => $style($this->starttime),
-                     'end' => '',
-                     'return' => $style($this->returntime));
-    }
-
-    public function is_active() {
-        if($this->returntime === null) {
-            return true;
-        }
-        return false;
-    }
-
-    public function end() {
-        $now = time();
-        $query = prepare('update `service` set `returntime`=? where `id`=?');
-        bind($query, 'ii', $now, $this->id);
-        execute($query);
-        $this->returntime = $now;
-        return true;
+    protected function update_fields() {
+        parent::update_fields();
     }
 }
 ?>