diff --git a/database/create.sh b/database/create.sh
index 9016ad3d5f19803e64f0e97b70c4a7e7428c8374..5a65f1c9e27b1aa0f0e05f7aeb193f97bb5f50e9 100755
--- a/database/create.sh
+++ b/database/create.sh
@@ -22,3 +22,7 @@ done
 for file in $(ls -B data/); do
 	psql $DB_NAME -f data/$file
 done
+
+for file in $(ls -B query/); do
+	psql $DB_NAME -f query/$file
+done
diff --git a/database/create/001-proinfo-oltp.sql b/database/create/001-proinfo-oltp.sql
index 6f5e7df328cd946b35f421383e0e08141eef0389..80cdd68577a4f3bbaa557e0fec5e2ac7459c9cf7 100644
--- a/database/create/001-proinfo-oltp.sql
+++ b/database/create/001-proinfo-oltp.sql
@@ -22,10 +22,10 @@ CREATE TABLE rejected_inventory (
         id           INTEGER,
         sch_id       INTEGER,
 	cit_id       INTEGER,
-	contact_date DATE,
-	project      project_enum,
-	inep         CHARACTER VARYING(18) not null, 
-	macaddr	     macaddr,
+	contact_date DATE NOT NULL,
+	project      INTEGER,
+	inep         CHARACTER VARYING(18) NOT NULL,
+	macaddr	     TEXT NOT NULL,
 	os_type      TEXT,
 	os_distro    TEXT,
 	os_kernel    TEXT,
diff --git a/database/load/000-sa.sql b/database/load/000-sa.sql
index f999fa14d4ad9fa443e3975e9250783e2c99ce6c..c18f36cfda0eda76133f2734298c21fb7cccc8fc 100644
--- a/database/load/000-sa.sql
+++ b/database/load/000-sa.sql
@@ -7,6 +7,9 @@ BEGIN
 END;
 $$ language plpgsql;
 
+CREATE OR REPLACE FUNCTION valid_macaddress(mac TEXT) RETURNS BOOLEAN AS $$
+       SELECT $1 ~* '(([0-9]|[a-f]){2}:){5}([0-9]|[a-f]){2}' AND $1 <> '00:00:00:00:00:00';
+$$ LANGUAGE SQL;
 
 -- Creates inventory staging area. This function should NOT be called directly.
 CREATE OR REPLACE FUNCTION sa_inventory_create() returns void as $$
@@ -31,13 +34,9 @@ BEGIN
 				s.id as sch_id,
 				s.cit_id,
 				i.contact_date,
-				CASE 	WHEN i.project = 0 THEN 'proinfo'::project_enum
-				 	WHEN i.project = 1 THEN 'uca_classmate'::project_enum
-				 	WHEN i.project = 2 THEN 'uca_server'::project_enum
-					WHEN i.project = 3 THEN 'projector'::project_enum
-				END as project,
+				i.project,
 				i.inep,
-				CAST(i.macaddr as MACADDR),
+				i.macaddr,
 				i.os_type,
 				i.os_distro,
 				i.os_kernel,
@@ -66,7 +65,7 @@ BEGIN
 		VALUES ('create sa inventory', start_ts, CLOCK_TIMESTAMP(), total_rows);
 
 	-- truncating OLTP table
-	--TRUNCATE TABLE proinfo_inventory;
+	TRUNCATE TABLE proinfo_inventory;
 
 END;
 $$ language plpgsql;
@@ -161,8 +160,6 @@ $$ language plpgsql;
 
 
 -- sanitize, removing invalid rows
--- TODO: Here we need to remove and log into another table rows that don't
--- relate to any school on dim_school. See LEFT JOIN on prior functions.
 CREATE OR REPLACE FUNCTION sa_sanitize() returns void as $$
 BEGIN
 	INSERT INTO rejected_inventory
@@ -175,7 +172,9 @@ BEGIN
 		disk1_model is NULL OR 
 		disk1_size is NULL OR 
 		disk1_used is NULL OR
-		macaddr = '00:00:00:00:00:00'::macaddr);
+		NOT valid_macaddress(macaddr) OR
+		project < 0 OR project > 3 OR
+		inep NOT IN (SELECT inep FROM dim_school));
 	DELETE FROM sa_inventory WHERE id IN (SELECT id FROM rejected_inventory);
 
 END;
diff --git a/database/load/002-dim_inventory.sql b/database/load/002-dim_inventory.sql
index 3acc283fa63bb60f5770de1ae2f118e0761517e7..5a79a811e6b472d088ae9e217699efea94b3fc44 100644
--- a/database/load/002-dim_inventory.sql
+++ b/database/load/002-dim_inventory.sql
@@ -1,5 +1,14 @@
 -- loads the table dim_inventory with inventories of new computers
 -- or inventories that had been modified.
+
+CREATE OR REPLACE FUNCTION to_project_enum(i INTEGER) RETURNS project_enum AS $$
+SELECT CASE WHEN $1 = 0 THEN 'proinfo'::project_enum
+	    WHEN $1 = 1 THEN 'uca_classmate'::project_enum
+	    WHEN $1 = 2 THEN 'uca_server'::project_enum
+	    WHEN $1 = 3 THEN 'projector'::project_enum
+	    END as project;
+$$ LANGUAGE SQL;
+
 CREATE OR REPLACE FUNCTION load_dim_inventory() returns void as $$
 DECLARE
 	inv_row record;
@@ -12,7 +21,7 @@ BEGIN
 	-- at the end of the function.
 	FOR inv_row IN SELECT * FROM sa_inventory s LEFT JOIN (SELECT * FROM dim_inventory
 		WHERE is_current = '1') d ON s.sch_id = d.sch_id AND
-		s.macaddr = d.macaddr AND NOT
+		s.macaddr::macaddr = d.macaddr AND NOT
                 (s.memory     >= d.memory * 0.9 AND
 		 s.memory     <= d.memory * 1.1 AND
 		 s.processor   = d.processor    AND
@@ -39,8 +48,8 @@ BEGIN
 			disk1_model, disk1_size, disk1_used, disk2_model,
 			disk2_size, disk2_used, memory, processor, os_type,
 			os_distro, os_kernel, is_current) VALUES
-			(inv_row.sch_id, inv_row.macaddr,
-			inv_row.contact_date, inv_row.project,
+			(inv_row.sch_id, inv_row.macaddr::macaddr,
+			inv_row.contact_date, to_project_enum(inv_row.project),
 			inv_row.disk1_model, inv_row.disk1_size,
 			inv_row.disk1_used, inv_row.disk2_model,
 			inv_row.disk2_size, inv_row.disk2_used,
diff --git a/database/load/003-fact_contact.sql b/database/load/003-fact_contact.sql
index 8053fad7fb36027cbe4de8efcfab8d2f701c6258..c9cb914448b614ed35a2a7a99902a1221a795895 100644
--- a/database/load/003-fact_contact.sql
+++ b/database/load/003-fact_contact.sql
@@ -16,7 +16,7 @@ BEGIN
 
 	-- 
 	INSERT INTO fact_contact (sch_id, cit_id, dat_id, macaddr)
-	(SELECT sch_id, cit_id, contact_date, macaddr FROM sa_inventory)
+	(SELECT sch_id, cit_id, contact_date, macaddr::macaddr FROM sa_inventory)
 	EXCEPT
 	(SELECT sch_id, cit_id, dat_id, macaddr FROM fact_contact WHERE dat_id >= result.min_date AND dat_id <= result.max_date);
 
diff --git a/database/query/availability.sql b/database/query/availability.sql
new file mode 100644
index 0000000000000000000000000000000000000000..c3a9f6f10c2058cf2337f59cce2d657965fb627f
--- /dev/null
+++ b/database/query/availability.sql
@@ -0,0 +1,213 @@
+/*Brasil*/
+create or replace function is_within(dat date, low integer, high integer) returns integer as $$
+select (case when $1 > current_date - $2 and $1 < current_date - $3 then 1 else 0 END);
+$$ language sql;
+
+create or replace function is_green(date) returns integer as $$
+select is_within($1, 10, 0);
+$$ language sql;
+
+create or replace function is_yellow(date) returns integer as $$
+select is_within($1, 20, 10);
+$$ language sql;
+
+create or replace function is_red(date) returns integer as $$
+select is_within($1, 30, 20);
+$$ language sql;
+
+create or replace function is_black(date) returns integer as $$
+select (case when $1 < current_date - 30 then 1 else 0 END) as black
+$$ language sql;
+
+create or replace function in_date_range(date) returns boolean as $$
+select (case when $1 > current_date - interval '6 months' then true else false END);
+$$ language sql; 
+
+create or replace function get_color(date) returns text as $$
+select (case when is_green($1) = 1 then 'green' else
+	case when is_yellow($1) = 1 then 'yellow' else
+	case when is_red($1) = 1 then 'red' else 'black' END END END);
+$$ language sql;
+
+create or replace function days_lastContact(date) returns int as $$
+select (current_date - $1);
+$$ language sql;
+
+create or replace function num_contactsMonth(macaddr, integer) returns integer as $$
+select count(*)::integer as contacted from fact_contact where macaddr = $1 and sch_id = $2 and (extract(month from current_date) = extract(month from dat_id)) and (extract(year from current_date) = extract(year from dat_id));
+$$ language sql;
+
+/* trocado 'dat_id' por 'load_date' ( aparentemente deu certo ); substituir em todas as outras funçoes */
+create or replace function availability_brazil(proj project_enum) returns table
+("Verde" bigint, "Amarelo" bigint, "Vermelho" bigint, "Preto" bigint) as $$
+select sum(green) as "Verde", sum(yellow) as "Amarelo", sum(red) as "Red", sum(black) as "Preto" from (
+  select is_green(load_date) as green,
+         is_yellow(load_date) as yellow,
+         is_red(load_date) as red,
+         is_black(load_date) as black
+  from dim_inventory i
+  where project = $1 and load_date > current_date - 40
+) as temp;
+$$ language sql;
+
+create or replace function availability_brazil_lines(proj project_enum) returns table
+("Verde" bigint, "Amarelo" bigint, "Vermelho" bigint, "Preto" bigint, "Data" date) as $$
+select sum(green), sum(yellow), sum(red), sum(black), dat_id 
+from (
+  select is_green(dat_id) as green,
+         is_yellow(dat_id) as yellow,
+         is_red(dat_id) as red,
+         is_black(dat_id) as black,
+	 dat_id
+  from dim_inventory i join fact_contact c on i.macaddr = c.macaddr
+  where project = $1 and in_date_range(dat_id)
+) as temp
+group by dat_id
+order by dat_id;
+$$ language sql;
+
+create or replace view school_and_location as select s.id as id, inep, s.name as school, address, cep, c.name as city, state, region
+from dim_school s join dim_city c on c.id = s.cit_id;
+
+/*Regiao*/
+create or replace function availability_region(proj project_enum) returns table
+("Verde" bigint, "Amarelo" bigint, "Vermelho" bigint, "Preto" bigint, "Regiao" text) as $$
+select sum(green), sum(yellow), sum(red), sum(black), region from (
+  select is_green(dat_id) as green,
+         is_yellow(dat_id) as yellow,
+         is_red(dat_id) as red,
+         is_black(dat_id) as black, sl.region
+  from dim_inventory i join fact_contact c on i.macaddr = c.macaddr
+  join school_and_location sl on i.sch_id = sl.id
+  where project = $1 and dat_id > current_date - 40
+) as temp
+group by region;
+$$ language sql;
+
+
+create or replace function availability_region_lines(proj project_enum) returns table
+("Verde" bigint, "Amarelo" bigint, "Vermelho" bigint, "Preto" bigint, "Data" date) as $$
+select sum(green), sum(yellow), sum(red), sum(black), dat_id
+from (
+  select is_green(dat_id) as green,
+         is_yellow(dat_id) as yellow,
+         is_red(dat_id) as red,
+         is_black(dat_id) as black,
+         dat_id
+  from dim_inventory i join fact_contact c on i.macaddr = c.macaddr
+  where project = $1 and in_date_range(dat_id)
+) as temp
+group by dat_id
+order by dat_id;
+$$ language sql;
+
+/*Estado*/
+create or replace function availability_state(proj project_enum, region text) returns table
+("Verde" bigint, "Amarelo" bigint, "Vermelho" bigint, "Preto" bigint, "Estado" text) as $$
+select sum(green), sum(yellow), sum(red), sum(black), state from (
+  select is_green(dat_id) as green,
+         is_yellow(dat_id) as yellow,
+         is_red(dat_id) as red,
+         is_black(dat_id) as black, sl.state
+  from dim_inventory i join fact_contact c on i.macaddr = c.macaddr
+  join school_and_location sl on i.sch_id = sl.id
+  where project = $1 and dat_id > current_date - 40
+  and region = $2
+) as temp
+group by state;
+$$ language sql;
+
+create or replace function availability_state_lines(proj project_enum, region text) returns table
+("Verde" bigint, "Amarelo" bigint, "Vermelho" bigint, "Preto" bigint, "Data" date) as $$
+select sum(green), sum(yellow), sum(red), sum(black), dat_id
+from (
+  select is_green(dat_id) as green,
+         is_yellow(dat_id) as yellow,
+         is_red(dat_id) as red,
+         is_black(dat_id) as black,
+         dat_id
+  from dim_inventory i join fact_contact c on i.macaddr = c.macaddr
+join school_and_location sl on i.sch_id = sl.id
+  where project = $1 and region = $2 and in_date_range(dat_id)
+) as temp
+group by dat_id
+order by dat_id;
+$$ language sql;
+
+/*Cidade*/
+create or replace function availability_city(proj project_enum, region text, state text) returns table
+("Verde" bigint, "Amarelo" bigint, "Vermelho" bigint, "Preto" bigint, "Cidade" text) as $$
+select sum(green), sum(yellow), sum(red), sum(black), city from (
+  select is_green(dat_id) as green,
+         is_yellow(dat_id) as yellow,
+         is_red(dat_id) as red,
+         is_black(dat_id) as black, sl.city
+  from dim_inventory i join fact_contact c on i.macaddr = c.macaddr
+  join school_and_location sl on i.sch_id = sl.id
+  where project = $1  and dat_id > current_date - 40
+  and region = $2
+  and state = $3
+) as temp
+group by city;
+$$ language sql;
+
+create or replace function availability_city_lines(proj project_enum, region text, state text) returns table
+("Verde" bigint, "Amarelo" bigint, "Vermelho" bigint, "Preto" bigint, "Data" date) as $$
+select sum(green), sum(yellow), sum(red), sum(black), dat_id
+from (
+  select is_green(dat_id) as green,
+         is_yellow(dat_id) as yellow,
+         is_red(dat_id) as red,
+         is_black(dat_id) as black,
+         dat_id
+  from dim_inventory i join fact_contact c on i.macaddr = c.macaddr
+join school_and_location sl on i.sch_id = sl.id
+  where project = $1 and region = $2 and state = $3 and in_date_range(dat_id)
+) as temp
+group by dat_id
+order by dat_id;
+$$ language sql;
+
+/*Relatório*/
+
+create or replace function availability_report(proj project_enum, region text, state text, city text) returns table
+("Date" date, "Maquina" macaddr, "Regiao" text, "Estado" text, "Cidade" text, "UltimoContato" date, "DiasAposUltimoContato" int, "ContatosNoMes" int, "Escola" text, "Cor" text) as $$
+select data, macad, region, state, city, ult_contact, days_last_contact, num_contacts_in_month, school, color
+from (
+  select (select max(end_time)::date from control) as data,
+	 i.macaddr as macad,
+	 region,
+	 state,
+	 city,
+	 c.dat_id as ult_contact,
+	 days_lastContact(max(c.dat_id)) as days_last_contact,
+	 num_contactsMonth(i.macaddr, i.sch_id) as num_contacts_in_month,
+	 school,
+	 get_color(max(dat_id)) as color
+  from dim_inventory i join fact_contact c on i.sch_id = c.sch_id and i.macaddr = c.macaddr
+join school_and_location sl on c.sch_id = sl.id
+  where project = $1 and region = $2 and state = $3 and city = $4
+  group by c.dat_id, i.macaddr, i.sch_id, region, state, city, school
+  order by i.sch_id
+) as temp;
+$$ language sql;
+
+		
+
+/*select to_char((select max(end_time) from  control), 'DD/MM/YYYY')
+                as load_date, machine, initcap(region) as region, state,
+                initcap(city) as city, last_contact, days_last_contact,
+                month_contacts, initcap(school) as school, color = 'green' as
+                green, color = 'yellow' as yellow, color = 'red' as red*/
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/database/queries/old_sa_to_new_oltp.sql b/database/query/old_sa_to_new_oltp.sql
similarity index 79%
rename from database/queries/old_sa_to_new_oltp.sql
rename to database/query/old_sa_to_new_oltp.sql
index d2717dec5bb8131ba35c0321536e3a3a325e6500..7da1f9f37b79dd485c7e5231cc5d592fa983d6fd 100644
--- a/database/queries/old_sa_to_new_oltp.sql
+++ b/database/query/old_sa_to_new_oltp.sql
@@ -1,4 +1,5 @@
-BEGIN;
+CREATE OR REPLACE FUNCTION migrate_old_sa() RETURNS VOID AS $$
+BEGIN
 INSERT INTO 
 	proinfo_inventory
 SELECT 
@@ -22,4 +23,5 @@ FROM
 	mectb00_staging_area
 WHERE
 	sa_data > '2012-07-01';
-COMMIT;
\ No newline at end of file
+END
+$$ LANGUAGE PLPGSQL;
\ No newline at end of file
diff --git a/database/test/proinfo_inventory.py b/database/test/proinfo_inventory.py
new file mode 100755
index 0000000000000000000000000000000000000000..7b535aed521c6ca0b511e547dca18fe030da901a
--- /dev/null
+++ b/database/test/proinfo_inventory.py
@@ -0,0 +1,101 @@
+#!/usr/bin/python
+
+import psycopg2
+import sys
+from datetime import date, timedelta
+import unittest
+
+# TODO: Unit tests
+
+MACHINE_PEAK = 10000
+DAYS = 3
+MACHINE_DOUBLE_COMM_RATIO = 0.12
+MACHINE_MULTI_COMM_RATIO = 0.02
+MACHINE_DECREASE_RATIO = 1.1
+MULTI_HD_TOTAL = 10
+HD_MODEL = 'foo'
+HD_SIZE = 100
+HD_USED = 0
+HD_EXTRA = 3
+INEP = 'PR97201405'
+TEMPLATE = "INSERT INTO proinfo_inventory (contact_date, project, inep, macaddr, os_type, os_distro, os_kernel, processor, memory, disk1_model, disk1_size, disk1_used, disk2_model, disk2_size, disk2_used, extra_hds) VALUES (%s, 0, '{0}', %s, 'Linux', 'Ubuntu 10.04.4 LTS', '2.6.35-25-generic', 'Intel(R) Celeron(R) CPU E1200  @', 160, '1016076 ST3160318AS_6VY4BK6R', 140, 5, %s, %s, %s, %s);".format(INEP)
+INITIAL_DATE = date(2012, 7, 1)
+
+def machine_increase(num):
+  return 10**num
+
+def clean_inventory(cur, machines):
+  cur.execute('TRUNCATE proinfo_inventory;')
+  for i in range(machines):
+    mac = gen_macaddress(i)
+    cur.execute('''DELETE FROM fact_contact AS f USING dim_school AS d
+WHERE f.sch_id = d.id AND f.macaddr = %s AND d.inep = %s;''', (mac, INEP))
+    cur.execute('''DELETE FROM dim_inventory AS i USING dim_school AS s
+WHERE i.macaddr = %s AND s.id = i.sch_id AND s.inep = %s''', (mac, INEP))
+
+def insert_data(cur):
+    for day in range(DAYS):
+        machines = machine_increase(day)
+        refresh_machines(machines, day, cur)
+    return max_machine(machines, DAYS - 1)
+
+def toHex(integer):
+  if integer < 16:
+    return '0' +  hex(integer)[2:]
+  else: return hex(integer)[2:]
+
+def gen_macaddress(integer):
+  integer += 1
+  p1 = integer & 255
+  p2 = (integer & 65535) >> 8
+  p3 = (integer & 16777215) >> 16
+  p4 = (integer & 2147483647) >> 24
+  return  "00:00:"  + toHex(p4) + ":" + toHex(p3) + ":" + toHex(p2) + ":" + toHex(p1)
+
+def refresh_machines(machines, day, cur):
+  contact = INITIAL_DATE + timedelta(days = day)
+  for i in updated_machines(machines, day):
+    macaddr = gen_macaddress(i)
+#        print "Mac {0}".format(macaddr)
+    if i < MULTI_HD_TOTAL:
+      cur.execute(TEMPLATE, (contact, macaddr, HD_MODEL, HD_SIZE, HD_USED, HD_EXTRA))
+    else:
+      cur.execute(TEMPLATE, (contact, macaddr, None, None, None, 0))
+
+def max_machine(machines, day):
+  return intround(machines / (MACHINE_DECREASE_RATIO * (day + 1)))
+
+def intround(f):
+  return int(round(f))
+
+def updated_machines(machines, day):
+  repetition = intround(machines * MACHINE_DOUBLE_COMM_RATIO)
+  multi = intround(machines * MACHINE_MULTI_COMM_RATIO)
+  i = 0
+#  print "Repetition {0}, multi {1}".format(repetition, multi)
+#  print "Max {0}".format(max_machine(machines, day))
+  while i < max_machine(machines, day):
+    if repetition > 0:
+      repetition -= 1
+      yield repetition
+    elif multi > 0:
+      multi -= 1
+      yield multi
+    else:
+      yield i
+      i += 1
+
+def get_connection(dbname, user):
+  return psycopg2.connect('dbname=' + dbname, 'user=' + user)
+
+if __name__ == '__main__':
+  if len(sys.argv) != 3:
+    sys.exit ("How to use: test_migration <database> <user>")
+  connection = get_connection(sys.argv[1], sys.argv[2])
+  cur = connection.cursor()
+  count = insert_data(cur)
+  print "Machines inserted {0}".format(count)
+  connection.commit()
+  clean_inventory(cur, count)
+  connection.commit()
+  connection.close()
diff --git a/database/test/test_inventory.py b/database/test/test_inventory.py
new file mode 100644
index 0000000000000000000000000000000000000000..14376ca769ce9dc7a6ff7d406fde1f29b89d4a68
--- /dev/null
+++ b/database/test/test_inventory.py
@@ -0,0 +1,105 @@
+#!/usr/bin/python
+
+import unittest
+import traceback
+from proinfo_inventory import get_connection, clean_inventory, insert_data
+
+def tearDownTest(connection, cur, count):
+    clean_inventory(cur, count)
+    connection.commit()
+    connection.close()
+
+
+def setUpTest():
+    connection = get_connection('msl09_pro', 'postgres')
+    cur = connection.cursor()
+    inserted = insert_data(cur)
+    cur.execute('SELECT load_dw();')
+    connection.commit()
+    return (connection, cur, inserted)
+
+def test_load_count(cur, inserted):
+    print 'All valid machines are loaded'
+    cur.execute("SELECT COUNT(*) FROM (SELECT macaddr, sch_id FROM dim_inventory GROUP BY macaddr, sch_id) AS t1;")
+    tup = cur.fetchone()
+    assert tup[0] == inserted
+
+def test_one_per_day(cur):
+    print 'There is only one inventory entry per day'
+    cur.execute("SELECT count(*) FROM dim_inventory GROUP BY load_date, sch_id, macaddr;")    
+    for tup in cur.fetchmany():
+        assert tup[0] == 1
+
+def test_one_per_day_multiple_load(cur):
+    print 'There is only one entry per day even if multiple loads happen'
+    inserted = insert_data(cur)
+    cur.execute("SELECT load_dw();")
+    cur.execute("SELECT count(*) FROM dim_inventory GROUP BY load_date, sch_id, macaddr;")    
+    for tup in cur.fetchall():
+        assert tup[0] == 1
+
+def test_inventory_data(cur):
+    print 'All inventory data is correctly inserted'
+    cur.execute('SELECT COUNT(*) FROM dim_inventory;')
+    total = cur.fetchone()[0]
+    cur.execute('''SELECT COUNT(*) FROM (SELECT * FROM dim_inventory
+WHERE os_type = %s AND os_distro = %s AND os_kernel = %s 
+AND processor = %s AND memory = %s AND disk1_model = %s AND disk1_size = %s
+AND disk1_used = %s) AS t1''', 
+                ('Linux', 'Ubuntu 10.04.4 LTS', '2.6.35-25-generic',
+                 'Intel(R) Celeron(R) CPU E1200  @', 160,
+                 '1016076 ST3160318AS_6VY4BK6R', 140, 5))
+    assert total == cur.fetchone()[0]
+
+def test_inventory_multi_hd(cur, count):
+    print 'Inventory is correctly inserted with many hds'
+    from proinfo_inventory import (HD_MODEL, HD_SIZE, HD_USED, HD_EXTRA,
+                                   MULTI_HD_TOTAL)
+    cur.execute('''SELECT COUNT(*) FROM (SELECT macaddr, sch_id FROM dim_inventory
+WHERE os_type = %s AND os_distro = %s AND os_kernel = %s 
+AND processor = %s AND memory = %s AND disk1_model = %s AND disk1_size = %s
+AND disk1_used = %s AND disk2_model = %s AND disk2_size = %s
+AND disk2_used = %s GROUP BY macaddr, sch_id) AS t1''',
+                ('Linux', 'Ubuntu 10.04.4 LTS', '2.6.35-25-generic',
+                 'Intel(R) Celeron(R) CPU E1200  @', 160,
+                 '1016076 ST3160318AS_6VY4BK6R', 140, 5, HD_MODEL, HD_SIZE, HD_USED))
+    matching = cur.fetchone()
+    assert MULTI_HD_TOTAL == matching[0]
+
+def test_clean_proinfo_inventory(cur):
+    print 'proinfo_inventory is cleared after load'
+    cur.execute('SELECT COUNT(*) FROM proinfo_inventory;')
+    count = cur.fetchone()[0]
+    print count
+    assert 0 == count
+
+def test_move_incomplete_proinfo_inventory(cur):
+    print 'Incomplete inventory entries are moved to rejected_inventory'
+    cur.execute("INSERT INTO proinfo_inventory(inep, macaddr) VALUES ('invalid', '0:0:0:0');")
+    cur.execute('SELECT load_dw();')
+    cur.execute("SELECT COUNT(*) FROM dim_inventory AS i JOIN dim_school AS s ON sch_id = i.id WHERE inep = 'invalid';")
+    count = cur.fetchone()[0]
+    print count
+    assert 0 == count
+
+def main():
+    conn, cur, count = setUpTest()
+
+    try:
+        test_clean_proinfo_inventory(cur)
+        test_load_count(cur, count)
+        test_one_per_day(cur)
+        test_inventory_data(cur)
+        test_inventory_multi_hd(cur, count)
+        test_move_incomplete_proinfo_inventory(cur)
+#        test_one_per_day_multiple_load(cur)
+        print 'Ok'
+
+    except AssertionError:
+        print 'There are failed tests ' + traceback.format_exc()
+    finally:
+        cur.execute('rollback;')
+        tearDownTest(conn, cur, count)
+
+if __name__ == '__main__':
+    main()