Compare commits
16 Commits
f87025c5a6
...
f75a1939a0
Author | SHA1 | Date |
---|---|---|
King Kévin | f75a1939a0 | |
King Kévin | b6f11afe3f | |
King Kévin | 199ac09b69 | |
King Kévin | 55234f0d7b | |
King Kévin | b6cc7ef060 | |
King Kévin | d530af9677 | |
King Kévin | f1a02d8fae | |
King Kévin | 3395d36c3c | |
King Kévin | cd601ede89 | |
King Kévin | dfe0f5c924 | |
King Kévin | a60e3063d1 | |
King Kévin | 149b9c9676 | |
King Kévin | ceeb101130 | |
King Kévin | feaee52376 | |
King Kévin | 4d891f17e7 | |
King Kévin | b02832b8d3 |
69
README.md
69
README.md
|
@ -7,6 +7,8 @@ Once the service is installed, there is a single page to search, add, delete, or
|
||||||
The only aspect not handled by the web frontend is the attachment deletion.
|
The only aspect not handled by the web frontend is the attachment deletion.
|
||||||
Just remove the files directly on the server under `public/attachments/<part_name>/`.
|
Just remove the files directly on the server under `public/attachments/<part_name>/`.
|
||||||
|
|
||||||
|
To add a part, start with the fresh home page without element selected, file the fields (at least the name), and click the update/add button.
|
||||||
|
You can then find it using the search box.
|
||||||
To import an LCSC part, simply go to the `/import/lcsc/Cxxxx` page and the part will be added to the database.
|
To import an LCSC part, simply go to the `/import/lcsc/Cxxxx` page and the part will be added to the database.
|
||||||
|
|
||||||
goals
|
goals
|
||||||
|
@ -39,7 +41,7 @@ components
|
||||||
|
|
||||||
Part information is:
|
Part information is:
|
||||||
|
|
||||||
- stored in a MariaDB/mySQL database
|
- stored in a sqlite3 database
|
||||||
- retrieved using a sinatra HTTP/REST server
|
- retrieved using a sinatra HTTP/REST server
|
||||||
- displayed using minimal HTML+JS pages
|
- displayed using minimal HTML+JS pages
|
||||||
|
|
||||||
|
@ -49,25 +51,64 @@ installation
|
||||||
install software dependencies (here for Arch linux):
|
install software dependencies (here for Arch linux):
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
sudo pacman -S mariadb
|
sudo pacman -S sqlite ruby ruby-rake
|
||||||
sudo pacman -S ruby-sinatra ruby-webrick
|
gem install json sqlite3 sinatra puma
|
||||||
pikaur -S ruby-mysql2
|
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
configure database
|
create database
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
sudo mariadb-install-db --user=mysql --basedir=/usr --datadir=/var/lib/mysql
|
sqlite partdb.db < schema.sql
|
||||||
sudo mysql
|
|
||||||
CREATE DATABASE partdb;
|
|
||||||
CREATE USER 'partdb'@localhost IDENTIFIED BY 'password';
|
|
||||||
GRANT ALL PRIVILEGES ON partdb.* TO 'partdb'@localhost;
|
|
||||||
exit
|
|
||||||
mysql --user=partdb --password=password --database=partdb < schema.sql
|
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
put the database access information in `credentials.json` and run `server.rb`.
|
now just run `server.rb`.
|
||||||
now go to http://localhost:4245 and you are ready to use it.
|
now go to http://localhost:4245 and you are ready to use it.
|
||||||
the port is defined in `server.rb`.
|
the port and database file is defined in `server.rb`.
|
||||||
|
|
||||||
use a proxy web server to handle the authentication, TLS, compression, ...
|
use a proxy web server to handle the authentication, TLS, compression, ...
|
||||||
|
|
||||||
|
KiCAD
|
||||||
|
=====
|
||||||
|
|
||||||
|
KiCAD can have a [KiCad database library](https://docs.kicad.org/master/en/eeschema/eeschema.html#database_libraries).
|
||||||
|
Running the `kicad_lib.rb` script will create tables (actually views) for each partdb category to be used by KiCAD.
|
||||||
|
The views are added without the `partdb.db` database file itself.
|
||||||
|
The script will also create the `partdb.kicad_dbl` library file.
|
||||||
|
This is the file to be used by KiCAD to add the database library.
|
||||||
|
But first you also need to install and configure ODBC so KiCAD can actually access the database:
|
||||||
|
|
||||||
|
~~~
|
||||||
|
# install ODBC
|
||||||
|
sudo pacman -S unixodbc
|
||||||
|
# install OBDC sqlite driver
|
||||||
|
pikaur -S sqliteodbc
|
||||||
|
# fix ODBC sqlite configuration
|
||||||
|
sudo sed -i 's|/usr/lib64/libsqlite3odbc.so|/usr/lib/libsqlite3odbc.so|g' /etc/odbcinst.ini
|
||||||
|
sudo sed -i 's|/usrl/lib64/libsqlite3odbc.so|/usr/lib/libsqlite3odbc.so|g' /etc/odbcinst.ini
|
||||||
|
sudo sed -i 's|/usr/lib64/libsqliteodbc.so|/usr/lib/libsqlite3odbc.so|g' /etc/odbcinst.ini
|
||||||
|
sudo sed -i 's|/usrl/lib64/libsqliteodbc.so|/usr/lib/libsqlite3odbc.so|g' /etc/odbcinst.ini
|
||||||
|
# add database
|
||||||
|
cat << EOF | sudo tee -a /etc/odbc.ini
|
||||||
|
[partdb]
|
||||||
|
Description=electronic parts database
|
||||||
|
Driver=SQLite
|
||||||
|
Database=<path to partdb.db>
|
||||||
|
Timeout=2000
|
||||||
|
EOF
|
||||||
|
# ensure it works
|
||||||
|
isql partdb
|
||||||
|
SELECT * FROM part LIMIT 1;
|
||||||
|
exit
|
||||||
|
~~~
|
||||||
|
|
||||||
|
service
|
||||||
|
=======
|
||||||
|
|
||||||
|
For convenience you can install the systemD service.
|
||||||
|
Be sure to adjust the path to the partdb script.
|
||||||
|
|
||||||
|
~~~
|
||||||
|
mkdir -p ~/.local/share/systemd/user/
|
||||||
|
cp partdb.service ~/.local/share/systemd/user/
|
||||||
|
systemctl --user start partdb.service
|
||||||
|
~~~
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
{
|
|
||||||
"host": "localhost",
|
|
||||||
"port": 3306,
|
|
||||||
"username": "partdb",
|
|
||||||
"password": "password",
|
|
||||||
"database": "partdb"
|
|
||||||
}
|
|
32
kicad_lib.rb
32
kicad_lib.rb
|
@ -7,15 +7,14 @@ https://docs.kicad.org/master/en/eeschema/eeschema.html#database_libraries
|
||||||
this script creates views from the partdb table so to create a database for KiCAD
|
this script creates views from the partdb table so to create a database for KiCAD
|
||||||
if wil also output the KiCad database library file
|
if wil also output the KiCad database library file
|
||||||
=end
|
=end
|
||||||
require 'mysql2'
|
require 'sqlite3'
|
||||||
require 'json'
|
require 'json'
|
||||||
|
|
||||||
CREDENTIALS = "credentials.json"
|
# database file
|
||||||
raise "database information #{CREDENTIALS} do not exist" unless File.file? CREDENTIALS
|
DB_PATH = "partdb.db"
|
||||||
credentials = {}
|
raise "DB file #{DB_PATH} does not exist" unless File.file? DB_PATH
|
||||||
JSON.parse(IO.read(CREDENTIALS)).each {|key,value| credentials[key.to_sym] = value}
|
db = SQLite3::Database.new(DB_PATH)
|
||||||
Mysql2::Client.default_query_options.merge!(:as => :hash)
|
db.results_as_hash = true
|
||||||
db = Mysql2::Client.new(credentials)
|
|
||||||
KICAD_FILE = "partdb.kicad_dbl"
|
KICAD_FILE = "partdb.kicad_dbl"
|
||||||
DEBUG = false # print debug information
|
DEBUG = false # print debug information
|
||||||
|
|
||||||
|
@ -25,7 +24,8 @@ prop2view = [{property: "kicad_symbol"}, {property: "kicad_footprint"}, {propert
|
||||||
prop2view.each do |prop|
|
prop2view.each do |prop|
|
||||||
puts prop[:property]
|
puts prop[:property]
|
||||||
prop[:table] = "part_" + prop[:property].downcase.gsub(/[- \/]/,"_")
|
prop[:table] = "part_" + prop[:property].downcase.gsub(/[- \/]/,"_")
|
||||||
view = "CREATE OR REPLACE VIEW #{prop[:table]} AS SELECT properties.part AS part, properties.value AS #{prop[:property]} FROM properties JOIN property ON property.id = properties.property WHERE property.name = '#{prop[:property]}'"
|
db.query("DROP VIEW IF EXISTS #{prop[:table]}")
|
||||||
|
view = "CREATE VIEW #{prop[:table]} AS SELECT properties.part AS part, properties.value AS #{prop[:property]} FROM properties JOIN property ON property.id = properties.property WHERE property.name = '#{prop[:property]}'"
|
||||||
puts view if DEBUG
|
puts view if DEBUG
|
||||||
db.query(view)
|
db.query(view)
|
||||||
end
|
end
|
||||||
|
@ -37,7 +37,8 @@ dist2view = [{property: "LCSC"}, {property: "JLCPCB"}, {property: "DigiKey"}]
|
||||||
dist2view.each do |prop|
|
dist2view.each do |prop|
|
||||||
puts prop[:property]
|
puts prop[:property]
|
||||||
prop[:table] = "part_" + prop[:property].downcase.gsub(/[- \/]/,"_")
|
prop[:table] = "part_" + prop[:property].downcase.gsub(/[- \/]/,"_")
|
||||||
view = "CREATE OR REPLACE VIEW #{prop[:table]} AS SELECT distribution.part AS part, distribution.sku AS #{prop[:property]} FROM distribution JOIN distributor ON distributor.id = distribution.distributor WHERE distributor.name = '#{prop[:property]}'"
|
db.query("DROP VIEW IF EXISTS #{prop[:table]}")
|
||||||
|
view = "CREATE VIEW #{prop[:table]} AS SELECT distribution.part AS part, distribution.sku AS #{prop[:property]} FROM distribution JOIN distributor ON distributor.id = distribution.distributor WHERE distributor.name = '#{prop[:property]}'"
|
||||||
puts view if DEBUG
|
puts view if DEBUG
|
||||||
db.query(view)
|
db.query(view)
|
||||||
end
|
end
|
||||||
|
@ -57,12 +58,13 @@ categories.uniq!
|
||||||
categories.each do |category|
|
categories.each do |category|
|
||||||
puts category
|
puts category
|
||||||
table = "kicad_lib_" + category.downcase.gsub(/[- \/]/,"_")
|
table = "kicad_lib_" + category.downcase.gsub(/[- \/]/,"_")
|
||||||
view = "CREATE OR REPLACE VIEW #{table} AS "
|
db.query("DROP VIEW IF EXISTS #{table}")
|
||||||
view += "SELECT part.id, part.name, "
|
view = "CREATE VIEW #{table} AS "
|
||||||
prop2view.each do |prop|
|
view += "SELECT part.id, part.name, part.description, "
|
||||||
|
(prop2view + dist2view).each do |prop|
|
||||||
view += "COALESCE(#{prop[:table]}1.#{prop[:property]},#{prop[:table]}2.#{prop[:property]}) AS #{prop[:property]}, "
|
view += "COALESCE(#{prop[:table]}1.#{prop[:property]},#{prop[:table]}2.#{prop[:property]}) AS #{prop[:property]}, "
|
||||||
end
|
end
|
||||||
view += "part.description FROM part "
|
view += "COALESCE(part.datasheet,parent.datasheet) AS datasheet FROM part "
|
||||||
view += "LEFT JOIN part AS parent ON parent.id = part.family "
|
view += "LEFT JOIN part AS parent ON parent.id = part.family "
|
||||||
(prop2view + dist2view).each do |prop|
|
(prop2view + dist2view).each do |prop|
|
||||||
view += "LEFT JOIN #{prop[:table]} AS #{prop[:table]}1 ON #{prop[:table]}1.part = part.id "
|
view += "LEFT JOIN #{prop[:table]} AS #{prop[:table]}1 ON #{prop[:table]}1.part = part.id "
|
||||||
|
@ -76,6 +78,8 @@ categories.each do |category|
|
||||||
library = {name: category, table: table, key: "name", symbols: "kicad_symbol", footprints: "kicad_footprint"}
|
library = {name: category, table: table, key: "name", symbols: "kicad_symbol", footprints: "kicad_footprint"}
|
||||||
library[:properties] = {description: "description"}
|
library[:properties] = {description: "description"}
|
||||||
library[:fields] = []
|
library[:fields] = []
|
||||||
|
library[:fields] << {name: "Description", column: "description", visible_on_add: false, visible_in_chooser: true, show_name: false, inherit_properties: true}
|
||||||
|
library[:fields] << {name: "Datasheet", column: "datasheet", visible_on_add: false, visible_in_chooser: true, show_name: false, inherit_properties: true}
|
||||||
(prop2view + dist2view).each do |prop|
|
(prop2view + dist2view).each do |prop|
|
||||||
next if prop[:property].start_with? "kicad_"
|
next if prop[:property].start_with? "kicad_"
|
||||||
library[:fields] << {name: prop[:property], column: prop[:property], visible_on_add: false, visible_in_chooser: true, show_name: false, inherit_properties: true}
|
library[:fields] << {name: prop[:property], column: prop[:property], visible_on_add: false, visible_in_chooser: true, show_name: false, inherit_properties: true}
|
||||||
|
@ -85,5 +89,5 @@ end
|
||||||
|
|
||||||
puts "writing KiCad database library file to #{KICAD_FILE}"
|
puts "writing KiCad database library file to #{KICAD_FILE}"
|
||||||
File.open(KICAD_FILE, "w") do |file|
|
File.open(KICAD_FILE, "w") do |file|
|
||||||
file.write kicad_dbl.to_json
|
file.write JSON.pretty_generate(kicad_dbl)
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
// the last search query
|
// the last search query
|
||||||
var last_search = null;
|
var last_search = null;
|
||||||
|
var next_search = null;
|
||||||
// the collection of parts
|
// the collection of parts
|
||||||
var parts = null;
|
var parts = null;
|
||||||
// last selected part
|
// last selected part
|
||||||
|
@ -21,23 +22,35 @@ function search()
|
||||||
{
|
{
|
||||||
const terms = document.getElementById('terms');
|
const terms = document.getElementById('terms');
|
||||||
if (terms && terms.value && terms.value.length >= 3) {
|
if (terms && terms.value && terms.value.length >= 3) {
|
||||||
} else {
|
const current_search = '/search?terms=' + terms.value;
|
||||||
return;
|
do_search(current_search);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
last_search = '/search?terms=' + terms.value;
|
function do_search(current_search)
|
||||||
let xhr = new XMLHttpRequest();
|
{
|
||||||
xhr.open('GET', last_search, true);
|
if (null == last_search) { // no request running
|
||||||
xhr.onload = function() {
|
last_search = current_search;
|
||||||
if (decodeURI(this.responseURL).endsWith(last_search)) {
|
let xhr = new XMLHttpRequest();
|
||||||
parts = JSON.parse(this.response);
|
xhr.open('GET', last_search, true);
|
||||||
results();
|
xhr.onload = function() {
|
||||||
}
|
if (decodeURI(this.responseURL).endsWith(last_search)) {
|
||||||
};
|
parts = JSON.parse(this.response);
|
||||||
xhr.onerror = function() {
|
results();
|
||||||
console.log("search call failed");
|
}
|
||||||
};
|
last_search = null;
|
||||||
xhr.send();
|
if (next_search) {
|
||||||
|
do_search(next_search);
|
||||||
|
next_search = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.onerror = function() {
|
||||||
|
console.log("search call failed");
|
||||||
|
};
|
||||||
|
xhr.send();
|
||||||
|
} else {
|
||||||
|
next_search = current_search; // save for next search
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function results()
|
function results()
|
||||||
|
|
18
schema.sql
18
schema.sql
|
@ -1,9 +1,9 @@
|
||||||
-- enable foreign key support in sqlite
|
-- enable foreign key support in sqlite
|
||||||
--PRAGMA foreign_keys = ON;
|
PRAGMA foreign_keys = ON;
|
||||||
|
|
||||||
-- part manufacturer
|
-- part manufacturer
|
||||||
CREATE TABLE IF NOT EXISTS manufacturer (
|
CREATE TABLE IF NOT EXISTS manufacturer (
|
||||||
id INTEGER AUTO_INCREMENT PRIMARY KEY, -- index
|
id INTEGER PRIMARY KEY AUTOINCREMENT, -- index
|
||||||
name TEXT NOT NULL UNIQUE, -- manufacturer (expanded version, without legal form)
|
name TEXT NOT NULL UNIQUE, -- manufacturer (expanded version, without legal form)
|
||||||
nick TEXT, -- manufacturer nickname
|
nick TEXT, -- manufacturer nickname
|
||||||
partof INTEGER, -- if the manufacturer has been acquired or is part of another
|
partof INTEGER, -- if the manufacturer has been acquired or is part of another
|
||||||
|
@ -14,7 +14,7 @@ CREATE TABLE IF NOT EXISTS manufacturer (
|
||||||
|
|
||||||
-- part distributor
|
-- part distributor
|
||||||
CREATE TABLE IF NOT EXISTS distributor (
|
CREATE TABLE IF NOT EXISTS distributor (
|
||||||
id INTEGER AUTO_INCREMENT PRIMARY KEY, -- index
|
id INTEGER PRIMARY KEY AUTOINCREMENT, -- index
|
||||||
name TEXT NOT NULL UNIQUE,
|
name TEXT NOT NULL UNIQUE,
|
||||||
homepage TEXT, -- URL to home page
|
homepage TEXT, -- URL to home page
|
||||||
product_page TEXT -- URL to product page (%s is replace by sku)
|
product_page TEXT -- URL to product page (%s is replace by sku)
|
||||||
|
@ -22,7 +22,7 @@ CREATE TABLE IF NOT EXISTS distributor (
|
||||||
|
|
||||||
-- the part itself
|
-- the part itself
|
||||||
CREATE TABLE IF NOT EXISTS part (
|
CREATE TABLE IF NOT EXISTS part (
|
||||||
id INTEGER AUTO_INCREMENT PRIMARY KEY, -- index
|
id INTEGER PRIMARY KEY AUTOINCREMENT, -- index
|
||||||
name TEXT NOT NULL UNIQUE,
|
name TEXT NOT NULL UNIQUE,
|
||||||
description TEXT, -- a short (searchable) description
|
description TEXT, -- a short (searchable) description
|
||||||
details TEXT, -- even more part details than just in the description
|
details TEXT, -- even more part details than just in the description
|
||||||
|
@ -48,7 +48,7 @@ CREATE TABLE IF NOT EXISTS assembly (
|
||||||
|
|
||||||
-- a part at a distributor
|
-- a part at a distributor
|
||||||
CREATE TABLE IF NOT EXISTS distribution (
|
CREATE TABLE IF NOT EXISTS distribution (
|
||||||
id INTEGER AUTO_INCREMENT PRIMARY KEY, -- index
|
id INTEGER PRIMARY KEY AUTOINCREMENT, -- index
|
||||||
part INTEGER NOT NULL, -- the part
|
part INTEGER NOT NULL, -- the part
|
||||||
distributor INTEGER NOT NULL, -- the part distributor
|
distributor INTEGER NOT NULL, -- the part distributor
|
||||||
sku TEXT NOT NULL, -- distributor part number
|
sku TEXT NOT NULL, -- distributor part number
|
||||||
|
@ -58,13 +58,13 @@ CREATE TABLE IF NOT EXISTS distribution (
|
||||||
|
|
||||||
-- part property
|
-- part property
|
||||||
CREATE TABLE IF NOT EXISTS property (
|
CREATE TABLE IF NOT EXISTS property (
|
||||||
id INTEGER AUTO_INCREMENT PRIMARY KEY, -- index
|
id INTEGER PRIMARY KEY AUTOINCREMENT, -- index
|
||||||
name TEXT NOT NULL -- property name (min V, ...)
|
name TEXT NOT NULL -- property name (min V, ...)
|
||||||
);
|
);
|
||||||
|
|
||||||
-- property value
|
-- property value
|
||||||
CREATE TABLE IF NOT EXISTS properties (
|
CREATE TABLE IF NOT EXISTS properties (
|
||||||
id INTEGER AUTO_INCREMENT PRIMARY KEY, -- index
|
id INTEGER PRIMARY KEY AUTOINCREMENT, -- index
|
||||||
part INTEGER NOT NULL, -- the part
|
part INTEGER NOT NULL, -- the part
|
||||||
property INTEGER NOT NULL,
|
property INTEGER NOT NULL,
|
||||||
value TEXT,
|
value TEXT,
|
||||||
|
@ -74,14 +74,14 @@ CREATE TABLE IF NOT EXISTS properties (
|
||||||
|
|
||||||
-- part location
|
-- part location
|
||||||
CREATE TABLE IF NOT EXISTS location (
|
CREATE TABLE IF NOT EXISTS location (
|
||||||
id INTEGER AUTO_INCREMENT PRIMARY KEY, -- index
|
id INTEGER PRIMARY KEY AUTOINCREMENT, -- index
|
||||||
name TEXT NOT NULL UNIQUE,
|
name TEXT NOT NULL UNIQUE,
|
||||||
container TEXT -- container type
|
container TEXT -- container type
|
||||||
);
|
);
|
||||||
|
|
||||||
-- local stock
|
-- local stock
|
||||||
CREATE TABLE IF NOT EXISTS inventory (
|
CREATE TABLE IF NOT EXISTS inventory (
|
||||||
id INTEGER AUTO_INCREMENT PRIMARY KEY, -- index
|
id INTEGER PRIMARY KEY AUTOINCREMENT, -- index
|
||||||
part INTEGER NOT NULL,
|
part INTEGER NOT NULL,
|
||||||
location INTEGER,
|
location INTEGER,
|
||||||
quantity INTEGER NOT NULL,
|
quantity INTEGER NOT NULL,
|
||||||
|
|
21
server.rb
21
server.rb
|
@ -8,23 +8,22 @@ Copyright (C) 2023 King Kévin <kingkevin@cuvoodoo.info>
|
||||||
SPDX-License-Identifier: GPL-3.0-or-later
|
SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
to install sinatra
|
to install sinatra
|
||||||
sudo pacman -S ruby-sinatra ruby-webrick
|
gem install sinatra puma
|
||||||
pikaur -S ruby-mysql2
|
|
||||||
=end
|
=end
|
||||||
require 'set'
|
require 'set'
|
||||||
require 'mysql2'
|
require 'sqlite3'
|
||||||
require 'json'
|
require 'json'
|
||||||
require 'sinatra'
|
require 'sinatra'
|
||||||
require 'uri'
|
require 'uri'
|
||||||
require 'net/http'
|
require 'net/http'
|
||||||
require 'cgi'
|
require 'cgi'
|
||||||
|
|
||||||
# allow dumping crashes in browser
|
|
||||||
DEBUG = false
|
DEBUG = false
|
||||||
# maximum number of parts returned
|
# maximum number of parts returned
|
||||||
PARTS_LIMIT = 100
|
PARTS_LIMIT = 100
|
||||||
# credentials for database
|
# database file
|
||||||
CREDENTIALS = "credentials.json"
|
DB_PATH = "partdb.db"
|
||||||
|
raise "DB file #{DB_PATH} does not exist" unless File.file? DB_PATH
|
||||||
# folder name for served pages
|
# folder name for served pages
|
||||||
PUBLIC = "public"
|
PUBLIC = "public"
|
||||||
# folder name for part attachments (in PUBLIC)
|
# folder name for part attachments (in PUBLIC)
|
||||||
|
@ -32,8 +31,6 @@ ATTACHMENTS = "attachments"
|
||||||
# port for this service
|
# port for this service
|
||||||
PORT = 4245
|
PORT = 4245
|
||||||
|
|
||||||
raise "database information #{CREDENTIALS} do not exist" unless File.file? CREDENTIALS
|
|
||||||
|
|
||||||
# open server
|
# open server
|
||||||
configure do
|
configure do
|
||||||
if DEBUG then
|
if DEBUG then
|
||||||
|
@ -63,10 +60,8 @@ before do
|
||||||
# all replies are only JSON
|
# all replies are only JSON
|
||||||
content_type 'application/json'
|
content_type 'application/json'
|
||||||
# open database
|
# open database
|
||||||
credentials = {}
|
@db = SQLite3::Database.new(DB_PATH)
|
||||||
JSON.parse(IO.read(CREDENTIALS)).each {|key,value| credentials[key.to_sym] = value}
|
@db.results_as_hash = true
|
||||||
Mysql2::Client.default_query_options.merge!(:as => :hash)
|
|
||||||
@db = Mysql2::Client.new(credentials)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
after do
|
after do
|
||||||
|
@ -314,6 +309,8 @@ def add_part(part)
|
||||||
field = "location"
|
field = "location"
|
||||||
part[field] = nil if part[field] and 0 == part[field].length
|
part[field] = nil if part[field] and 0 == part[field].length
|
||||||
if part[field] then
|
if part[field] then
|
||||||
|
delete = @db.prepare("DELETE FROM inventory WHERE part = ?")
|
||||||
|
delete.execute(part["id"])
|
||||||
statement = @db.prepare("SELECT id FROM #{field} WHERE LOWER(name) = ?")
|
statement = @db.prepare("SELECT id FROM #{field} WHERE LOWER(name) = ?")
|
||||||
ref = statement.execute(part[field].downcase).to_a[0]
|
ref = statement.execute(part[field].downcase).to_a[0]
|
||||||
unless ref then
|
unless ref then
|
||||||
|
|
Loading…
Reference in New Issue