WHERE record > 0 AND label LIKE $4 || '%' AND owning_lib = $2;
$$ LANGUAGE SQL;
+/** Returns the next (by ID) non-deleted copy */
+CREATE FUNCTION evergreen.next_copy (copy_id BIGINT) RETURNS asset.copy AS $$
+ DECLARE copy asset.copy%ROWTYPE;
+ DECLARE max_id BIGINT;
+BEGIN
+ SELECT INTO max_id max(id) FROM asset.copy;
+ WHILE TRUE LOOP
+ copy_id := copy_id + 1;
+ IF copy_id > max_id THEN
+ RETURN NULL;
+ END IF;
+ SELECT INTO copy * FROM asset.copy WHERE id = copy_id;
+ IF NOT copy.deleted THEN
+ RETURN copy;
+ END IF;
+ END LOOP;
+ RETURN NULL;
+END;
+$$ LANGUAGE PLPGSQL;
+
+
+
+
+/**
+ * Creates circulations
+ */
+CREATE FUNCTION evergreen.populate_circ (
+ patron_barcode TEXT,
+ copy_barcode TEXT,
+ circ_lib INTEGER,
+ duration_rule TEXT,
+ recurring_fine_rule TEXT,
+ max_fine_rule TEXT,
+ overdue BOOLEAN
+)
+RETURNS void AS $$
+ INSERT INTO action.circulation (
+ usr, target_copy, circ_lib, circ_staff, renewal_remaining,
+ grace_period, duration, recurring_fine, max_fine, duration_rule,
+ recurring_fine_rule, max_fine_rule, due_date )
+ VALUES (
+ (SELECT usr FROM actor.card WHERE barcode = $1),
+ (SELECT id FROM asset.copy WHERE barcode = $2 AND NOT deleted),
+ $3, -- circ_lib
+ 1, -- circ_staff
+ (SELECT max_renewals FROM config.rule_circ_duration WHERE name = $4),
+ (SELECT grace_period FROM config.rule_recurring_fine WHERE name = $5),
+ (SELECT normal FROM config.rule_circ_duration WHERE name = $4),
+ (SELECT normal FROM config.rule_recurring_fine WHERE name = $5),
+ (SELECT amount FROM config.rule_max_fine WHERE name = $6),
+ $4, -- duration_rule
+ $5, -- recurring_fine_rule
+ $6, -- max_fine_rule
+ CASE WHEN $7 THEN -- due_date
+ (DATE(NOW() - -- subtract duration from now() for overdues
+ (SELECT normal FROM config.rule_circ_duration WHERE name = $4))
+ || ' 23:59:59')::TIMESTAMP -- due_date
+ ELSE
+ (DATE(NOW() +
+ (SELECT normal FROM config.rule_circ_duration WHERE name = $4))
+ || ' 23:59:59')::TIMESTAMP -- due_date
+ END
+ );
+$$ LANGUAGE SQL;
+
+
+
+
--- /dev/null
+
+
+/* NOTE: fine generator should be run after loading to produce billings */
+
+/**
+ * create 3 regular circs w/ varying (stock) rules and 3 overdue
+ * circs for the fisrt 2 (by ID) users in each profile group.
+ * target copies start at ID 1 and progress upward by ID from
+ * there, skipping deleted copies.
+ * TODO: vary the rules more
+ */
+DO $$
+ DECLARE grp INTEGER;
+ DECLARE recipient INTEGER;
+ DECLARE copy asset.copy%ROWTYPE;
+BEGIN
+ copy := evergreen.next_copy(0);
+
+ FOR grp IN SELECT id FROM permission.grp_tree LOOP
+ FOR recipient IN SELECT id FROM actor.usr
+ WHERE profile = grp ORDER BY id LIMIT 2 LOOP
+
+ copy := evergreen.next_copy(copy.id);
+ PERFORM evergreen.populate_circ(
+ (SELECT barcode FROM actor.card WHERE usr = recipient),
+ copy.barcode, copy.circ_lib,
+ 'default', 'default', 'default', FALSE
+ );
+
+ copy := evergreen.next_copy(copy.id);
+ PERFORM evergreen.populate_circ(
+ (SELECT barcode FROM actor.card WHERE usr = recipient),
+ copy.barcode, copy.circ_lib,
+ 'default', 'default', 'overdue_min', FALSE
+ );
+
+ copy := evergreen.next_copy(copy.id);
+ PERFORM evergreen.populate_circ(
+ (SELECT barcode FROM actor.card WHERE usr = recipient),
+ copy.barcode, copy.circ_lib,
+ 'default', 'default', 'overdue_max', FALSE
+ );
+
+ -- overdues...
+
+ copy := evergreen.next_copy(copy.id);
+ PERFORM evergreen.populate_circ(
+ (SELECT barcode FROM actor.card WHERE usr = recipient),
+ copy.barcode, copy.circ_lib,
+ 'default', 'default', 'default', TRUE
+ );
+
+ copy := evergreen.next_copy(copy.id);
+ PERFORM evergreen.populate_circ(
+ (SELECT barcode FROM actor.card WHERE usr = recipient),
+ copy.barcode, copy.circ_lib,
+ 'default', 'default', 'overdue_min', TRUE
+ );
+
+ copy := evergreen.next_copy(copy.id);
+ PERFORM evergreen.populate_circ(
+ (SELECT barcode FROM actor.card WHERE usr = recipient),
+ copy.barcode, copy.circ_lib,
+ 'default', 'default', 'overdue_max', TRUE
+ );
+
+ END LOOP;
+ END LOOP;
+END $$;
+
+