Several changes:
- The inventory page now shows status of seen products as of when they were registered, not as of now. - Renamed a placeholder in fragments.html to be more intuitive. - Added a type field to the event table in the database, so that complete events can be constructed without complex logic. - Refactored to support the above changes
This commit is contained in:
parent
763d1c6ba5
commit
ef756e36b4
@ -78,6 +78,7 @@ create table `user` (
|
||||
create table `event` (
|
||||
`id` bigint(20) not null auto_increment,
|
||||
primary key(`id`),
|
||||
`type` varchar(64),
|
||||
`product` bigint(20) not null,
|
||||
constraint `e_f_product`
|
||||
foreign key(`product`) references `product`(`id`),
|
||||
@ -123,7 +124,8 @@ create table `inventory_product` (
|
||||
`product` bigint(20) not null,
|
||||
constraint `i_f_product`
|
||||
foreign key(`product`) references `product`(`id`),
|
||||
unique `uniq_inventory_product`(`inventory`, `product`)
|
||||
unique `uniq_inventory_product`(`inventory`, `product`),
|
||||
`regtime` bigint(20) not null
|
||||
) character set utf8mb4,
|
||||
collate utf8mb4_unicode_ci;
|
||||
|
||||
|
@ -95,7 +95,7 @@
|
||||
¤serial¤
|
||||
</td>
|
||||
<td>
|
||||
¤available¤
|
||||
¤note¤
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
@ -5,7 +5,7 @@ class Event {
|
||||
protected $starttime = 0;
|
||||
protected $returntime = null;
|
||||
|
||||
protected static function create_event($product) {
|
||||
protected static function create_event($product, $type) {
|
||||
$status = $product->get_status();
|
||||
if($status != 'available') {
|
||||
$emsg = '';
|
||||
@ -28,11 +28,18 @@ class Event {
|
||||
}
|
||||
throw new Exception($emsg);
|
||||
}
|
||||
switch($type) {
|
||||
case 'loan':
|
||||
case 'service':
|
||||
break;
|
||||
default:
|
||||
throw new Excpetion("Invalid argument '$type'");
|
||||
}
|
||||
$now = time();
|
||||
$insert = prepare('insert into
|
||||
`event`(`product`, `starttime`)
|
||||
values (?, ?)');
|
||||
bind($insert, 'ii', $product->get_id(), $now);
|
||||
$insert = prepare('insert into `event`
|
||||
(`product`, `type`, `starttime`)
|
||||
values (?, ?, ?)');
|
||||
bind($insert, 'isi', $product->get_id(), $type, $now);
|
||||
execute($insert);
|
||||
$event_id = $insert->insert_id;
|
||||
return new Event($event_id);
|
||||
|
@ -15,12 +15,12 @@ class Inventory {
|
||||
execute($start);
|
||||
$invid = $start->insert_id;
|
||||
$prodid = '';
|
||||
$register = prepare('insert into
|
||||
`inventory_product`(`inventory`, `product`)
|
||||
values (?, ?)');
|
||||
foreach(get_items('loan_active') as $loan) {
|
||||
$prodid = $loan->get_product()->get_id();
|
||||
bind($register, 'ii', $invid, $prodid);
|
||||
$register = prepare('insert into `inventory_product`
|
||||
(`inventory`, `product`, `regtime`)
|
||||
values (?, ?, ?)');
|
||||
foreach(get_items('event_active') as $event) {
|
||||
$prodid = $event->get_product()->get_id();
|
||||
bind($register, 'iii', $invid, $prodid, $now);
|
||||
execute($register);
|
||||
}
|
||||
return new Inventory($invid);
|
||||
@ -75,9 +75,10 @@ class Inventory {
|
||||
}
|
||||
|
||||
public function add_product($product) {
|
||||
$add = prepare('insert into `inventory_product`(`inventory`, `product`)
|
||||
values (?, ?)');
|
||||
bind($add, 'ii', $this->id, $product->get_id());
|
||||
$add = prepare('insert into `inventory_product`
|
||||
(`inventory`, `product`, `regtime`)
|
||||
values (?, ?, ?)');
|
||||
bind($add, 'iii', $this->id, $product->get_id(), time());
|
||||
try {
|
||||
execute($add);
|
||||
} catch(Exception $e) {
|
||||
@ -107,6 +108,21 @@ class Inventory {
|
||||
return $out;
|
||||
}
|
||||
|
||||
public function get_product_regtime($product) {
|
||||
$invid = $this->id;
|
||||
$prodid = $product->get_id();
|
||||
$search = prepare('select `regtime` from `inventory_product`
|
||||
where `inventory` = ? and `product` = ?');
|
||||
bind($search, 'ii', $invid, $prodid);
|
||||
execute($search);
|
||||
$result = result_single($search);
|
||||
if(!$result) {
|
||||
$emsg = "Inventory $invid has no reference to product $prodid.";
|
||||
throw new Exception($emsg);
|
||||
}
|
||||
return $result['regtime'];
|
||||
}
|
||||
|
||||
public function get_unseen_products() {
|
||||
$all = get_items('product');
|
||||
$out = array();
|
||||
|
@ -5,10 +5,12 @@ class Loan extends Event {
|
||||
|
||||
public static function create_loan($user, $product, $endtime) {
|
||||
begin_trans();
|
||||
$event = parent::create_event($product);
|
||||
$event = parent::create_event($product, 'loan');
|
||||
$event_id = $event->get_id();
|
||||
$insert = prepare('insert into `loan`(`user`, `endtime`) values (?, ?)');
|
||||
bind($insert, 'ii', $user->get_id(), strtotime($endtime . ' 13:00'));
|
||||
$insert = prepare('insert into `loan`(`event`, `user`, `endtime`)
|
||||
values (?, ?, ?)');
|
||||
$endtime .= '13:00';
|
||||
bind($insert, 'iii', $event_id, $user->get_id(), strtotime($endtime));
|
||||
execute($insert);
|
||||
commit_trans();
|
||||
return new Loan($event_id);
|
||||
|
@ -134,15 +134,16 @@ abstract class Page extends Responder {
|
||||
'name' => $product->get_name(),
|
||||
'page' => 'products'),
|
||||
$this->fragments['item_link']);
|
||||
$available = 'Tillgänglig';
|
||||
$note = 'Tillgänglig';
|
||||
$status = $product->get_status();
|
||||
switch($status) {
|
||||
case 'discarded':
|
||||
$available = 'Skrotad '.$discarded;
|
||||
$discarded = format_date($product->get_discardtime());
|
||||
$note = 'Skrotad '.$discarded;
|
||||
break;
|
||||
case 'service':
|
||||
$service = $product->get_active_service();
|
||||
$available = 'På service sedan '
|
||||
$note = 'På service sedan '
|
||||
.format_date($service->get_starttime());
|
||||
break;
|
||||
case 'on_loan':
|
||||
@ -153,18 +154,18 @@ abstract class Page extends Responder {
|
||||
'id' => $user->get_id(),
|
||||
'page' => 'users'),
|
||||
$this->fragments['item_link']);
|
||||
$available = 'Utlånad till '.$userlink;
|
||||
$note = 'Utlånad till '.$userlink;
|
||||
if($loan->is_overdue()) {
|
||||
$available .= ', försenad';
|
||||
$note .= ', försenad';
|
||||
} else {
|
||||
$available .= ', åter '.format_date($loan->get_endtime());
|
||||
$note .= ', slutdatum '.format_date($loan->get_endtime());
|
||||
}
|
||||
break;
|
||||
}
|
||||
$rows .= replace(array('available' => $available,
|
||||
$rows .= replace(array('status' => $status,
|
||||
'item_link' => $prodlink,
|
||||
'serial' => $product->get_serial(),
|
||||
'status' => $status,
|
||||
'item_link' => $prodlink),
|
||||
'note' => $note,),
|
||||
$this->fragments['product_row']);
|
||||
}
|
||||
return replace(array('rows' => $rows),
|
||||
@ -240,6 +241,63 @@ abstract class Page extends Responder {
|
||||
$this->fragments['history_table']);
|
||||
}
|
||||
|
||||
final protected function build_seen_table($products, $inventory) {
|
||||
$rows = '';
|
||||
foreach($products as $product) {
|
||||
$prodid = $product->get_id();
|
||||
$prodlink = replace(array('id' => $prodid,
|
||||
'name' => $product->get_name(),
|
||||
'page' => 'products'),
|
||||
$this->fragments['item_link']);
|
||||
$regtime = $inventory->get_product_regtime($product);
|
||||
$event = $product->get_historic_event($regtime);
|
||||
$status = '';
|
||||
$note = '';
|
||||
if(!$event) {
|
||||
$discardtime = $product->get_discardtime();
|
||||
if($discardtime && $discardtime < $regtime) {
|
||||
$status = 'discarded';
|
||||
$note = 'Skrotad '.format_date($discardtime);
|
||||
} else {
|
||||
$status = 'available';
|
||||
}
|
||||
} else if($event instanceof Service) {
|
||||
$status = 'service';
|
||||
$note = 'På service sedan '.format_date($event->get_starttime());
|
||||
$returntime = $event->get_returntime();
|
||||
if($returntime) {
|
||||
$note .= ', åter den '.format_date($returntime);
|
||||
}
|
||||
} else if($event instanceof Loan) {
|
||||
$user = $event->get_user();
|
||||
$userlink = replace(array('name' => $user->get_displayname(),
|
||||
'id' => $user->get_id(),
|
||||
'page' => 'users'),
|
||||
$this->fragments['item_link']);
|
||||
$status = 'on_loan';
|
||||
$note = 'Utlånad till '.$userlink;
|
||||
$returntime = $event->get_returntime();
|
||||
if($event->get_endtime() < $regtime) {
|
||||
$status = 'overdue';
|
||||
$note .= ', försenad';
|
||||
} else {
|
||||
$note .= ', slutdatum '.format_date($event->get_endtime());
|
||||
}
|
||||
if($returntime) {
|
||||
$note .= ', återlämnad '.format_date($returntime);
|
||||
}
|
||||
}
|
||||
$rows .= replace(array('status' => $status,
|
||||
'item_link' => $prodlink,
|
||||
'serial' => $product->get_serial(),
|
||||
'note' => $note),
|
||||
$this->fragments['product_row']);
|
||||
}
|
||||
return replace(array('rows' => $rows),
|
||||
$this->fragments['product_table']);
|
||||
|
||||
}
|
||||
|
||||
final protected function build_inventory_details($inventory,
|
||||
$interactive = true) {
|
||||
$startdate = format_date($inventory->get_starttime());
|
||||
@ -272,7 +330,7 @@ abstract class Page extends Responder {
|
||||
$out .= replace(array('title' => 'Inventerade artiklar'),
|
||||
$this->fragments['subtitle']);
|
||||
if($seen) {
|
||||
$out .= $this->build_product_table($seen);
|
||||
$out .= $this->build_seen_table($seen, $inventory);
|
||||
} else {
|
||||
$out .= 'Inga artiklar inventerade.';
|
||||
}
|
||||
|
@ -148,10 +148,7 @@ class Product {
|
||||
return $this->createtime;
|
||||
}
|
||||
|
||||
public function get_discardtime($format = true) {
|
||||
if($this->discardtime && $format) {
|
||||
return gmdate('Y-m-d', $this->discardtime);
|
||||
}
|
||||
public function get_discardtime() {
|
||||
return $this->discardtime;
|
||||
}
|
||||
|
||||
@ -325,7 +322,7 @@ class Product {
|
||||
}
|
||||
|
||||
public function get_status() {
|
||||
if($this->get_discardtime(false)) {
|
||||
if($this->get_discardtime()) {
|
||||
return 'discarded';
|
||||
}
|
||||
if($this->get_active_service()) {
|
||||
@ -341,6 +338,32 @@ class Product {
|
||||
return 'on_loan';
|
||||
}
|
||||
|
||||
public function get_historic_event($time) {
|
||||
$search = prepare("select `id`,`type` from `event`
|
||||
where `product` = ?
|
||||
and `starttime` < ?
|
||||
and ( `returntime` > ?
|
||||
or `returntime` is null )");
|
||||
bind($search, 'iii', $this->id, $time, $time);
|
||||
execute($search);
|
||||
$result = result_single($search);
|
||||
if(!$result) {
|
||||
return null;
|
||||
}
|
||||
$id = $result['id'];
|
||||
$type = $result['type'];
|
||||
switch($type) {
|
||||
case 'service':
|
||||
return new Service($id);
|
||||
break;
|
||||
case 'loan':
|
||||
return new Loan($id);
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Invalid type '$type'");
|
||||
}
|
||||
}
|
||||
|
||||
public function get_active_loan() {
|
||||
$find = prepare('select `id` from `event`
|
||||
inner join `loan`
|
||||
@ -357,23 +380,25 @@ class Product {
|
||||
|
||||
public function get_history() {
|
||||
$out = array();
|
||||
foreach(array('loan' => function($id) { return new Loan($id);},
|
||||
'service' => function($id) { return new Service($id);})
|
||||
as $type => $func) {
|
||||
$find = prepare('select `id` from `event` '
|
||||
."inner join `$type` "
|
||||
."on `event`.`id` = `$type`.`event` "
|
||||
.'where `product`=? order by `starttime` desc');
|
||||
bind($find, 'i', $this->id);
|
||||
execute($find);
|
||||
$items = result_list($find);
|
||||
foreach($items as $item) {
|
||||
$out[] = $func($item['id']);
|
||||
$find = prepare('select `id`,`type` from `event` '
|
||||
.'where `product`=? order by `starttime` desc');
|
||||
bind($find, 'i', $this->id);
|
||||
execute($find);
|
||||
$items = result_list($find);
|
||||
foreach($items as $item) {
|
||||
$id = $item['id'];
|
||||
switch($item['type']) {
|
||||
case 'service':
|
||||
$out[] = new Service($id);
|
||||
break;
|
||||
case 'loan':
|
||||
$out[] = new Loan($id);
|
||||
break;
|
||||
default:
|
||||
$type = $item['type'];
|
||||
throw new Exception("Invalid type '$type'");
|
||||
}
|
||||
}
|
||||
usort($out, function($a, $b) {
|
||||
return $a->get_starttime() < $b->get_starttime();
|
||||
});
|
||||
return $out;
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
class Service extends Event {
|
||||
public static function create_service($product) {
|
||||
begin_trans();
|
||||
$event = parent::create_event($product);
|
||||
$event = parent::create_event($product, 'service');
|
||||
$event_id = $event->get_id();
|
||||
$insert = prepare('insert into `service`(`event`) values (?)');
|
||||
bind($insert, 'i', $event_id);
|
||||
|
@ -108,18 +108,18 @@ function get_ids($type) {
|
||||
case 'product':
|
||||
$append = 'where `discardtime` is null';
|
||||
break;
|
||||
case 'loan':
|
||||
case 'product_discarded':
|
||||
$type = 'product';
|
||||
$append = 'where `discardtime` is not null';
|
||||
break;
|
||||
case 'event':
|
||||
break;
|
||||
case 'event_active':
|
||||
$type = 'event';
|
||||
$append = 'where `returntime` is null';
|
||||
break;
|
||||
case 'inventory':
|
||||
break;
|
||||
case 'product_discarded':
|
||||
$append = 'where `discardtime` is not null';
|
||||
$type = 'product';
|
||||
break;
|
||||
case 'loan_active':
|
||||
$append = 'where `returntime` is null';
|
||||
$type = 'loan';
|
||||
break;
|
||||
case 'inventory_old':
|
||||
$append = 'where `endtime` is not null order by `id` desc';
|
||||
$type = 'inventory';
|
||||
@ -156,10 +156,10 @@ function get_items($type) {
|
||||
return new Product($id);
|
||||
};
|
||||
break;
|
||||
case 'loan':
|
||||
case 'loan_active':
|
||||
case 'event':
|
||||
case 'event_active':
|
||||
$construct = function($id) {
|
||||
return new Loan($id);
|
||||
return new Event($id);
|
||||
};
|
||||
break;
|
||||
case 'inventory':
|
||||
|
Loading…
x
Reference in New Issue
Block a user