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