const UTC_NOW = "strftime('%Y-%m-%dT%H:%M:%fZ', 'now')"; export const INIT_META = ` CREATE TABLE IF NOT EXISTS meta ( "key" TEXT PRIMARY KEY, value TEXT NOT NULL ); INSERT OR IGNORE INTO meta ("key", value) VALUES ('version', '1'); `; export const INIT_LANGUAGE = ` CREATE TABLE IF NOT EXISTS language ( id INTEGER PRIMARY KEY AUTOINCREMENT, iso639 TEXT NOT NULL COLLATE NOCASE UNIQUE ); `; export const INIT_TAX = ` CREATE TABLE IF NOT EXISTS tax ( id INTEGER PRIMARY KEY AUTOINCREMENT, rate NUMERIC NOT NULL UNIQUE ); INSERT OR IGNORE INTO tax (rate) VALUES (0), (7), (19); `; export const INIT_CATEGORY = ` CREATE TABLE IF NOT EXISTS category ( id INTEGER PRIMARY KEY AUTOINCREMENT, parent_id INTEGER, sort INTEGER NOT NULL DEFAULT 0, updated_at TEXT NOT NULL DEFAULT (${UTC_NOW}), FOREIGN KEY (parent_id) REFERENCES category(id) ON DELETE NO ACTION ); `; export const INIT_PIC = ` CREATE TABLE IF NOT EXISTS pic ( id INTEGER PRIMARY KEY AUTOINCREMENT, w INTEGER NOT NULL, h INTEGER NOT NULL, size INTEGER NOT NULL, hash TEXT NOT NULL UNIQUE, thumbw INTEGER NOT NULL, thumbh INTEGER NOT NULL, thumbhash TEXT NOT NULL, smallthumbw INTEGER NOT NULL, smallthumbh INTEGER NOT NULL, smallthumbbinary BLOB NOT NULL, source TEXT NOT NULL ); `; export const INIT_COMPANY = ` CREATE TABLE IF NOT EXISTS company ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL COLLATE NOCASE UNIQUE, root_category_id INTEGER, default_language_id INTEGER, taxrate INTEGER, reducedtaxrate INTEGER, taxfreerate INTEGER, poscustomergroup_id INTEGER NOT NULL, FOREIGN KEY (root_category_id) REFERENCES category(id) ON DELETE SET NULL, FOREIGN KEY (default_language_id) REFERENCES language(id) ON DELETE SET NULL, FOREIGN KEY (taxrate) REFERENCES tax(id) ON DELETE NO ACTION, FOREIGN KEY (reducedtaxrate) REFERENCES tax(id) ON DELETE NO ACTION, FOREIGN KEY (taxfreerate) REFERENCES tax(id) ON DELETE NO ACTION, FOREIGN KEY (poscustomergroup_id) REFERENCES customergroup(id) ON DELETE NO ACTION ); `; export const INIT_GOOGLE_AUTH = ` CREATE TABLE IF NOT EXISTS google_auth ( id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT NOT NULL COLLATE NOCASE UNIQUE, picture TEXT, picturebinary BLOB, sub TEXT, created_at TEXT NOT NULL DEFAULT (${UTC_NOW}), selected_company INTEGER, FOREIGN KEY (selected_company) REFERENCES company(id) ON DELETE SET NULL ); CREATE UNIQUE INDEX IF NOT EXISTS UQ_google_auth_sub ON google_auth(sub) WHERE sub IS NOT NULL; `; export const INIT_CUSTOMERGROUP = ` CREATE TABLE IF NOT EXISTS customergroup ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, sort INTEGER NOT NULL DEFAULT 0, company_id INTEGER, updated_at TEXT NOT NULL DEFAULT (${UTC_NOW}), FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE ); `; /* The FK is declared inline in INIT_COMPANY; SQLite cannot add it later. */ export const INIT_COMPANY_POS_CUSTOMERGROUP_FK = ''; export const INIT_ENTITY = ` CREATE TABLE IF NOT EXISTS entity ( id INTEGER PRIMARY KEY AUTOINCREMENT, customergroup_id INTEGER NOT NULL, company_id INTEGER, first_name TEXT, name TEXT NOT NULL, "number" TEXT, created_at TEXT NOT NULL DEFAULT (${UTC_NOW}), updated_at TEXT NOT NULL DEFAULT (${UTC_NOW}), FOREIGN KEY (customergroup_id) REFERENCES customergroup(id) ON DELETE CASCADE, FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE ); `; /** * SQLite cannot index a joined view, so company_id is denormalized onto entity. * Triggers keep it synchronized with the entity's customer group. */ export const INIT_ENTITY_COMPANY_NUMBER_UQ = ` CREATE UNIQUE INDEX IF NOT EXISTS UQ_entity_company_number ON entity(company_id, "number") WHERE "number" IS NOT NULL; CREATE TRIGGER IF NOT EXISTS TR_entity_set_company_insert AFTER INSERT ON entity BEGIN UPDATE entity SET company_id = (SELECT company_id FROM customergroup WHERE id = NEW.customergroup_id) WHERE id = NEW.id; END; CREATE TRIGGER IF NOT EXISTS TR_entity_set_company_update AFTER UPDATE OF customergroup_id ON entity BEGIN UPDATE entity SET company_id = (SELECT company_id FROM customergroup WHERE id = NEW.customergroup_id) WHERE id = NEW.id; END; CREATE TRIGGER IF NOT EXISTS TR_customergroup_sync_entity_company AFTER UPDATE OF company_id ON customergroup BEGIN UPDATE entity SET company_id = NEW.company_id WHERE customergroup_id = NEW.id; END; `; export const INIT_ENTITYADDRESS = ` CREATE TABLE IF NOT EXISTS entityaddress ( id INTEGER PRIMARY KEY AUTOINCREMENT, entity_id INTEGER NOT NULL, first_name TEXT, name TEXT, street TEXT, streetnumber TEXT, zip TEXT, city TEXT, county TEXT, addresstype TEXT NOT NULL, sort INTEGER NOT NULL DEFAULT 0, FOREIGN KEY (entity_id) REFERENCES entity(id) ON DELETE CASCADE ); `; export const INIT_ENTITYCONTACT = ` CREATE TABLE IF NOT EXISTS entitycontact ( id INTEGER PRIMARY KEY AUTOINCREMENT, entity_id INTEGER NOT NULL, contacttype TEXT NOT NULL, contact TEXT NOT NULL, sort INTEGER NOT NULL DEFAULT 0, FOREIGN KEY (entity_id) REFERENCES entity(id) ON DELETE CASCADE ); `; export const INIT_UNIT = ` CREATE TABLE IF NOT EXISTS unit ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, si TEXT NOT NULL, basesi TEXT NOT NULL, basesifactor REAL NOT NULL, UNIQUE (company_id, si), FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE NO ACTION ); `; export const INIT_UNITTEXT = ` CREATE TABLE IF NOT EXISTS unittext ( id INTEGER PRIMARY KEY AUTOINCREMENT, unit_id INTEGER NOT NULL, language_id INTEGER NOT NULL, symbol TEXT NOT NULL, name TEXT NOT NULL, UNIQUE (unit_id, language_id), FOREIGN KEY (unit_id) REFERENCES unit(id) ON DELETE CASCADE, FOREIGN KEY (language_id) REFERENCES language(id) ON DELETE CASCADE ); `; export const INIT_OPTIONSLIST = ` CREATE TABLE IF NOT EXISTS optionslist (id INTEGER PRIMARY KEY AUTOINCREMENT); `; export const INIT_ARTICLELIST = ` CREATE TABLE IF NOT EXISTS articlelist (id INTEGER PRIMARY KEY AUTOINCREMENT); `; export const INIT_BRAND = ` CREATE TABLE IF NOT EXISTS brand ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, name TEXT NOT NULL COLLATE NOCASE, gsprpinfo TEXT, UNIQUE (company_id, name), FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE NO ACTION ); `; export const INIT_ARTICLE = ` CREATE TABLE IF NOT EXISTS article ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, sku TEXT COLLATE NOCASE, unit_id INTEGER NOT NULL, unitamount REAL NOT NULL, weight REAL NOT NULL, track_stock INTEGER NOT NULL DEFAULT 0, brand_id INTEGER, articlelist_id INTEGER, optionslist_id INTEGER, is_parent INTEGER NOT NULL DEFAULT 0, parentarticle_id INTEGER, parentsort INTEGER NOT NULL DEFAULT 0, parentattributename_id INTEGER, created_at TEXT NOT NULL DEFAULT (${UTC_NOW}), updated_at TEXT NOT NULL DEFAULT (${UTC_NOW}), UNIQUE (company_id, sku), FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE, FOREIGN KEY (unit_id) REFERENCES unit(id) ON DELETE NO ACTION, FOREIGN KEY (brand_id) REFERENCES brand(id) ON DELETE SET NULL, FOREIGN KEY (articlelist_id) REFERENCES articlelist(id) ON DELETE SET NULL, FOREIGN KEY (optionslist_id) REFERENCES optionslist(id) ON DELETE SET NULL, FOREIGN KEY (parentarticle_id) REFERENCES article(id) ON DELETE NO ACTION, FOREIGN KEY (parentattributename_id) REFERENCES attributename(id) ON DELETE NO ACTION ); CREATE UNIQUE INDEX IF NOT EXISTS UQ_article_parentarticle_parentsort ON article(parentarticle_id, parentsort) WHERE parentarticle_id IS NOT NULL; `; export const INIT_ARTICLEEAN = ` CREATE TABLE IF NOT EXISTS articleean ( id INTEGER PRIMARY KEY AUTOINCREMENT, article_id INTEGER NOT NULL, ean TEXT NOT NULL, FOREIGN KEY (article_id) REFERENCES article(id) ON DELETE CASCADE ); CREATE UNIQUE INDEX IF NOT EXISTS UQ_articleean_article_ean ON articleean(article_id, ean); CREATE INDEX IF NOT EXISTS IX_articleean_ean ON articleean(ean); `; export const INIT_ARTICLEPIC = ` CREATE TABLE IF NOT EXISTS articlepic ( id INTEGER PRIMARY KEY AUTOINCREMENT, article_id INTEGER NOT NULL, pic_id INTEGER NOT NULL, sort INTEGER NOT NULL DEFAULT 0, UNIQUE (article_id, pic_id), UNIQUE (article_id, sort), FOREIGN KEY (article_id) REFERENCES article(id) ON DELETE CASCADE, FOREIGN KEY (pic_id) REFERENCES pic(id) ON DELETE CASCADE ); `; export const INIT_BRANDPIC = ` CREATE TABLE IF NOT EXISTS brandpic ( id INTEGER PRIMARY KEY AUTOINCREMENT, brand_id INTEGER NOT NULL, pic_id INTEGER NOT NULL, sort INTEGER NOT NULL DEFAULT 0, UNIQUE (brand_id, pic_id), UNIQUE (brand_id, sort), FOREIGN KEY (brand_id) REFERENCES brand(id) ON DELETE CASCADE, FOREIGN KEY (pic_id) REFERENCES pic(id) ON DELETE CASCADE ); `; export const INIT_ATTRIBUTEVALUEPIC = ` CREATE TABLE IF NOT EXISTS attributevaluepic ( id INTEGER PRIMARY KEY AUTOINCREMENT, attributevalue_id INTEGER NOT NULL, pic_id INTEGER NOT NULL, sort INTEGER NOT NULL DEFAULT 0, UNIQUE (attributevalue_id, pic_id), UNIQUE (attributevalue_id, sort), FOREIGN KEY (attributevalue_id) REFERENCES attributevalue(id) ON DELETE CASCADE, FOREIGN KEY (pic_id) REFERENCES pic(id) ON DELETE CASCADE ); `; export const INIT_ARTICLELISTARTICLE = ` CREATE TABLE IF NOT EXISTS articlelistarticle ( id INTEGER PRIMARY KEY AUTOINCREMENT, articlelist_id INTEGER NOT NULL, article_id INTEGER NOT NULL, count INTEGER NOT NULL DEFAULT 1, sort INTEGER NOT NULL DEFAULT 0, UNIQUE (articlelist_id, article_id), UNIQUE (articlelist_id, sort), FOREIGN KEY (articlelist_id) REFERENCES articlelist(id) ON DELETE CASCADE, FOREIGN KEY (article_id) REFERENCES article(id) ON DELETE CASCADE ); `; export const INIT_OPTIONSLISTARTICLE = ` CREATE TABLE IF NOT EXISTS optionslistarticle ( id INTEGER PRIMARY KEY AUTOINCREMENT, optionslist_id INTEGER NOT NULL, article_id INTEGER NOT NULL, count INTEGER NOT NULL DEFAULT 1, sort INTEGER NOT NULL DEFAULT 0, mandated INTEGER NOT NULL DEFAULT 0, UNIQUE (optionslist_id, article_id), UNIQUE (optionslist_id, sort), FOREIGN KEY (optionslist_id) REFERENCES optionslist(id) ON DELETE CASCADE, FOREIGN KEY (article_id) REFERENCES article(id) ON DELETE CASCADE ); `; export const INIT_CATEGORYARTICLE = ` CREATE TABLE IF NOT EXISTS categoryarticle ( id INTEGER PRIMARY KEY AUTOINCREMENT, category_id INTEGER NOT NULL, article_id INTEGER NOT NULL, UNIQUE (category_id, article_id), FOREIGN KEY (category_id) REFERENCES category(id) ON DELETE NO ACTION, FOREIGN KEY (article_id) REFERENCES article(id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS IX_categoryarticle_article_category ON categoryarticle(article_id, category_id); `; export const INIT_CATEGORYPIC = ` CREATE TABLE IF NOT EXISTS categorypic ( id INTEGER PRIMARY KEY AUTOINCREMENT, category_id INTEGER NOT NULL, pic_id INTEGER NOT NULL, sort INTEGER NOT NULL DEFAULT 0, UNIQUE (category_id, pic_id), UNIQUE (category_id, sort), FOREIGN KEY (category_id) REFERENCES category(id) ON DELETE CASCADE, FOREIGN KEY (pic_id) REFERENCES pic(id) ON DELETE CASCADE ); `; export const INIT_CATEGORYTEXT = ` CREATE TABLE IF NOT EXISTS categorytext ( id INTEGER PRIMARY KEY AUTOINCREMENT, category_id INTEGER NOT NULL, language_id INTEGER NOT NULL, name TEXT NOT NULL, slug TEXT NOT NULL, seo TEXT, "desc" TEXT, UNIQUE (category_id, language_id), FOREIGN KEY (category_id) REFERENCES category(id) ON DELETE CASCADE, FOREIGN KEY (language_id) REFERENCES language(id) ON DELETE CASCADE ); `; export const INIT_ARTICLENAME = ` CREATE TABLE IF NOT EXISTS articletext ( id INTEGER PRIMARY KEY AUTOINCREMENT, article_id INTEGER NOT NULL, language_id INTEGER NOT NULL, name TEXT NOT NULL, slug TEXT NOT NULL, seo TEXT, "desc" TEXT, UNIQUE (article_id, language_id), FOREIGN KEY (article_id) REFERENCES article(id) ON DELETE CASCADE, FOREIGN KEY (language_id) REFERENCES language(id) ON DELETE CASCADE ); `; export const INIT_PRICE = ` CREATE TABLE IF NOT EXISTS price ( id INTEGER PRIMARY KEY AUTOINCREMENT, tax_id INTEGER NOT NULL, article_id INTEGER NOT NULL, minmultiplier NUMERIC NOT NULL DEFAULT 1, customergroup_id INTEGER NOT NULL, net REAL NOT NULL, FOREIGN KEY (tax_id) REFERENCES tax(id) ON DELETE CASCADE, FOREIGN KEY (article_id) REFERENCES article(id) ON DELETE CASCADE, FOREIGN KEY (customergroup_id) REFERENCES customergroup(id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS IX_price_article_cg_mult ON price(article_id, customergroup_id, minmultiplier, net, tax_id); `; export const INIT_ARTICLE_SUPPLIER = ` CREATE TABLE IF NOT EXISTS articlesupplier ( id INTEGER PRIMARY KEY AUTOINCREMENT, article_id INTEGER NOT NULL, entity_id INTEGER NOT NULL, net REAL, tax_id INTEGER, sku TEXT, stock REAL, pu REAL NOT NULL DEFAULT 1, sort INTEGER NOT NULL DEFAULT 0, UNIQUE (article_id, entity_id), UNIQUE (article_id, sort), FOREIGN KEY (article_id) REFERENCES article(id) ON DELETE CASCADE, FOREIGN KEY (entity_id) REFERENCES entity(id) ON DELETE NO ACTION, FOREIGN KEY (tax_id) REFERENCES tax(id) ON DELETE NO ACTION ); CREATE INDEX IF NOT EXISTS IX_articlesupplier_article_entity ON articlesupplier(article_id, entity_id); `; export const INIT_MANIFEST = ` CREATE TABLE IF NOT EXISTS manifest ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, "number" TEXT NOT NULL, "type" TEXT NOT NULL, entity_id INTEGER, external_number TEXT, "date" TEXT NOT NULL DEFAULT (${UTC_NOW}), created_at TEXT NOT NULL DEFAULT (${UTC_NOW}), FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE NO ACTION, FOREIGN KEY (entity_id) REFERENCES entity(id) ON DELETE NO ACTION ); CREATE UNIQUE INDEX IF NOT EXISTS UQ_manifest_company_type_number ON manifest (company_id, "type", "number"); `; export const INIT_MANIFESTARTICLE = ` CREATE TABLE IF NOT EXISTS manifestarticle ( id INTEGER PRIMARY KEY AUTOINCREMENT, manifest_id INTEGER NOT NULL, sku TEXT, name TEXT, pu REAL NOT NULL DEFAULT 1, amount REAL NOT NULL, net REAL NOT NULL, comment TEXT, rebate REAL NOT NULL DEFAULT 0, taxrate REAL NOT NULL DEFAULT 0, FOREIGN KEY (manifest_id) REFERENCES manifest(id) ON DELETE CASCADE ); `; export const INIT_WAREHOUSE = ` CREATE TABLE IF NOT EXISTS warehouse ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, name TEXT NOT NULL COLLATE NOCASE, sort INTEGER NOT NULL DEFAULT 0, UNIQUE (company_id, name), FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE ); `; /* SQLite has no SQL Server ledger tables; constraints preserve the base shape. */ export const INIT_LEDGER = ` CREATE TABLE IF NOT EXISTS ledger ( id INTEGER PRIMARY KEY AUTOINCREMENT, manifestarticle_id INTEGER NOT NULL, warehouse_id INTEGER, transaction_type TEXT NOT NULL, amount REAL NOT NULL, transaction_text TEXT NOT NULL, hash_version INTEGER NOT NULL, prev_hash TEXT, created_at TEXT NOT NULL DEFAULT (${UTC_NOW}), FOREIGN KEY (manifestarticle_id) REFERENCES manifestarticle(id) ON DELETE NO ACTION, FOREIGN KEY (warehouse_id) REFERENCES warehouse(id) ON DELETE NO ACTION ); `; export const INIT_NUMBERS = ` CREATE TABLE IF NOT EXISTS numbers ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, "type" TEXT NOT NULL, prefix TEXT NOT NULL DEFAULT '', padding INTEGER NOT NULL DEFAULT 0, "next" INTEGER NOT NULL DEFAULT 1, UNIQUE (company_id, "type"), FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE ); `; export const INIT_COMPANYUSER = ` CREATE TABLE IF NOT EXISTS companyuser ( id INTEGER PRIMARY KEY AUTOINCREMENT, google_auth_id INTEGER NOT NULL, company_id INTEGER NOT NULL, UNIQUE (google_auth_id, company_id), FOREIGN KEY (google_auth_id) REFERENCES google_auth(id) ON DELETE CASCADE, FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE ); `; export const INIT_MODELCONVERSATION = ` CREATE TABLE IF NOT EXISTS modelconversation ( id INTEGER PRIMARY KEY AUTOINCREMENT, companyuser_id INTEGER NOT NULL, provider TEXT NOT NULL, model TEXT NOT NULL, created_at TEXT NOT NULL DEFAULT (${UTC_NOW}), updated_at TEXT NOT NULL DEFAULT (${UTC_NOW}), state TEXT NOT NULL DEFAULT 'idle' CHECK (state IN ('idle', 'busy')), started_by INTEGER, -- id of the conversation that started this one as a subagent; deliberately NOT a foreign key FOREIGN KEY (companyuser_id) REFERENCES companyuser(id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS IX_modelconversation_companyuser ON modelconversation (companyuser_id, updated_at); CREATE INDEX IF NOT EXISTS IX_modelconversation_started_by ON modelconversation (started_by); `; export const INIT_MODELVFS = ` CREATE TABLE IF NOT EXISTS modelvfs ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, name TEXT NOT NULL, mime TEXT NOT NULL, meta TEXT, created_at TEXT NOT NULL DEFAULT (${UTC_NOW}), updated_at TEXT NOT NULL DEFAULT (${UTC_NOW}), FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE, UNIQUE (company_id, name) ); CREATE INDEX IF NOT EXISTS IX_modelvfs_company_name ON modelvfs (company_id, name); `; export const INIT_MODELMESSAGE = ` CREATE TABLE IF NOT EXISTS modelmessage ( id INTEGER PRIMARY KEY AUTOINCREMENT, conversation_id INTEGER NOT NULL, created_at TEXT NOT NULL DEFAULT (${UTC_NOW}), role TEXT NOT NULL CHECK (role IN ('system', 'user', 'assistant', 'tool', 'reasoning', 'usage')), message TEXT NOT NULL, FOREIGN KEY (conversation_id) REFERENCES modelconversation(id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS IX_modelmessage_conversation ON modelmessage (conversation_id, id); `; export const INIT_ARTICLEHISTORY = ` CREATE TABLE IF NOT EXISTS articlehistory ( id INTEGER PRIMARY KEY AUTOINCREMENT, article_id INTEGER NOT NULL, companyuser_id INTEGER, "date" TEXT NOT NULL DEFAULT (${UTC_NOW}), "text" TEXT NOT NULL, meta TEXT, FOREIGN KEY (article_id) REFERENCES article(id) ON DELETE CASCADE, FOREIGN KEY (companyuser_id) REFERENCES companyuser(id) ON DELETE SET NULL ); `; export const INIT_COMPANYHISTORY = ` CREATE TABLE IF NOT EXISTS companyhistory ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, companyuser_id INTEGER, "date" TEXT NOT NULL DEFAULT (${UTC_NOW}), "text" TEXT NOT NULL, FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE, FOREIGN KEY (companyuser_id) REFERENCES companyuser(id) ON DELETE SET NULL ); `; export const INIT_ARTICLETOMBSTONE = ` CREATE TABLE IF NOT EXISTS articletombstone ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, article_id INTEGER, sku TEXT COLLATE NOCASE, name TEXT, taxrate NUMERIC, net REAL, deleted_at TEXT NOT NULL DEFAULT (${UTC_NOW}), CHECK (article_id IS NOT NULL OR sku IS NOT NULL), FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS IX_articletombstone_company_deleted ON articletombstone (company_id, deleted_at); `; export const INIT_ENTITYHISTORY = ` CREATE TABLE IF NOT EXISTS entityhistory ( id INTEGER PRIMARY KEY AUTOINCREMENT, entity_id INTEGER NOT NULL, companyuser_id INTEGER, "date" TEXT NOT NULL DEFAULT (${UTC_NOW}), "text" TEXT NOT NULL, FOREIGN KEY (entity_id) REFERENCES entity(id) ON DELETE CASCADE, FOREIGN KEY (companyuser_id) REFERENCES companyuser(id) ON DELETE NO ACTION ); `; export const INIT_COMPANYSETTING = ` CREATE TABLE IF NOT EXISTS companysetting ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, "key" TEXT NOT NULL, value TEXT NOT NULL, frontend INTEGER NOT NULL DEFAULT 0, writeonly INTEGER NOT NULL DEFAULT 0, UNIQUE (company_id, "key"), FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE ); `; export const INIT_POSTERMINAL = ` CREATE TABLE IF NOT EXISTS posterminal ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, name TEXT NOT NULL, token TEXT, pairingpin TEXT, paired_at TEXT, clientserial TEXT, maxknowntombstoneid INTEGER, root_category_id INTEGER, sync_root_articles INTEGER NOT NULL DEFAULT 1, lastseen_at TEXT, updated_at TEXT NOT NULL DEFAULT (${UTC_NOW}), FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE, FOREIGN KEY (root_category_id) REFERENCES category(id) ON DELETE SET NULL ); CREATE UNIQUE INDEX IF NOT EXISTS UQ_posterminal_token ON posterminal(token) WHERE token IS NOT NULL; `; export const INIT_POSTERMINALCATEGORY = ` CREATE TABLE IF NOT EXISTS posterminalcategory ( id INTEGER PRIMARY KEY AUTOINCREMENT, posterminal_id INTEGER NOT NULL, category_id INTEGER NOT NULL, UNIQUE (posterminal_id, category_id), FOREIGN KEY (posterminal_id) REFERENCES posterminal(id) ON DELETE CASCADE, FOREIGN KEY (category_id) REFERENCES category(id) ON DELETE NO ACTION ); `; export const INIT_PRINTER = ` CREATE TABLE IF NOT EXISTS printer ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, address TEXT NOT NULL, type TEXT NOT NULL CHECK (type IN ('esc/pos', 'zpl', 'ipp')), model TEXT, serial TEXT, sort INTEGER NOT NULL DEFAULT 0, "desc" TEXT, FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE ); `; export const INIT_LABELTEMPLATE = ` CREATE TABLE IF NOT EXISTS labeltemplate ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, name TEXT NOT NULL, width INTEGER NOT NULL, height INTEGER NOT NULL, dpi INTEGER NOT NULL CHECK (dpi IN (203, 300)), type TEXT NOT NULL CHECK (type IN ('zpl')), content TEXT NOT NULL, thumb BLOB, FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE ); `; export const INIT_FILE = ` CREATE TABLE IF NOT EXISTS "file" ( id INTEGER PRIMARY KEY AUTOINCREMENT, hash TEXT NOT NULL, mimetype TEXT NOT NULL, name TEXT NOT NULL, size INTEGER NOT NULL, created TEXT NOT NULL DEFAULT (${UTC_NOW}), modified TEXT NOT NULL DEFAULT (${UTC_NOW}), thumbx INTEGER, thumby INTEGER, meta TEXT ); `; export const INIT_MANIFESTATTACHMENT = ` CREATE TABLE IF NOT EXISTS manifestattachment ( id INTEGER PRIMARY KEY AUTOINCREMENT, manifest_id INTEGER NOT NULL, file_id INTEGER NOT NULL, sort INTEGER NOT NULL DEFAULT 0, UNIQUE (manifest_id, sort), FOREIGN KEY (manifest_id) REFERENCES manifest(id) ON DELETE CASCADE, FOREIGN KEY (file_id) REFERENCES "file"(id) ON DELETE CASCADE ); `; export const INIT_MANIFESTATTACHMENT_TRIGGER = ` CREATE TRIGGER IF NOT EXISTS TR_manifestattachment_delete_file AFTER DELETE ON manifestattachment BEGIN DELETE FROM "file" WHERE id = OLD.file_id AND NOT EXISTS ( SELECT 1 FROM manifestattachment WHERE file_id = OLD.file_id ); END; `; export const INIT_PROPERTYNAME = ` CREATE TABLE IF NOT EXISTS propertyname ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, name TEXT NOT NULL, sort INTEGER NOT NULL DEFAULT 0, exclusive INTEGER NOT NULL DEFAULT 0, FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE, UNIQUE (company_id, name) ); `; export const INIT_ARTICLEPROPERTY = ` CREATE TABLE IF NOT EXISTS articleproperty ( id INTEGER PRIMARY KEY AUTOINCREMENT, article_id INTEGER NOT NULL, property_id INTEGER NOT NULL, value TEXT NOT NULL, sort INTEGER NOT NULL DEFAULT 0, FOREIGN KEY (article_id) REFERENCES article(id) ON DELETE CASCADE, FOREIGN KEY (property_id) REFERENCES propertyname(id) ON DELETE NO ACTION ); `; export const INIT_ATTRIBUTENAME = ` CREATE TABLE IF NOT EXISTS attributename ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, name TEXT NOT NULL, sort INTEGER NOT NULL DEFAULT 0, exclusive INTEGER NOT NULL DEFAULT 0, FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE, UNIQUE (company_id, name) ); `; export const INIT_ATTRIBUTEVALUE = ` CREATE TABLE IF NOT EXISTS attributevalue ( id INTEGER PRIMARY KEY AUTOINCREMENT, attribute_id INTEGER NOT NULL, value TEXT NOT NULL, sort INTEGER NOT NULL DEFAULT 0, FOREIGN KEY (attribute_id) REFERENCES attributename(id) ON DELETE CASCADE, UNIQUE (attribute_id, value) ); `; export const INIT_ARTICLEATTRIBUTEVALUE = ` CREATE TABLE IF NOT EXISTS articleattributevalue ( id INTEGER PRIMARY KEY AUTOINCREMENT, article_id INTEGER NOT NULL, attributevalue_id INTEGER NOT NULL, sort INTEGER NOT NULL DEFAULT 0, FOREIGN KEY (article_id) REFERENCES article(id) ON DELETE CASCADE, FOREIGN KEY (attributevalue_id) REFERENCES attributevalue(id) ON DELETE NO ACTION, UNIQUE (article_id, attributevalue_id) ); `; export const INIT_CATEGORYPROPERTY = ` CREATE TABLE IF NOT EXISTS categoryproperty ( id INTEGER PRIMARY KEY AUTOINCREMENT, category_id INTEGER NOT NULL, property_id INTEGER NOT NULL, value TEXT NOT NULL, sort INTEGER NOT NULL DEFAULT 0, FOREIGN KEY (category_id) REFERENCES category(id) ON DELETE CASCADE, FOREIGN KEY (property_id) REFERENCES propertyname(id) ON DELETE NO ACTION ); `; export const INIT_CATEGORYATTRIBUTEVALUE = ` CREATE TABLE IF NOT EXISTS categoryattributevalue ( id INTEGER PRIMARY KEY AUTOINCREMENT, category_id INTEGER NOT NULL, attributevalue_id INTEGER NOT NULL, sort INTEGER NOT NULL DEFAULT 0, FOREIGN KEY (category_id) REFERENCES category(id) ON DELETE CASCADE, FOREIGN KEY (attributevalue_id) REFERENCES attributevalue(id) ON DELETE CASCADE, UNIQUE (category_id, attributevalue_id) ); `; export const INIT_ACCOUNT = ` CREATE TABLE IF NOT EXISTS account ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, "type" TEXT NOT NULL, "name" TEXT NOT NULL, FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE ); `; export const INIT_PAYMENT = ` CREATE TABLE IF NOT EXISTS payment ( id INTEGER PRIMARY KEY AUTOINCREMENT, account_id INTEGER NOT NULL, manifest_id INTEGER NOT NULL, "type" TEXT NOT NULL, amount REAL NOT NULL, FOREIGN KEY (account_id) REFERENCES account(id) ON DELETE CASCADE, FOREIGN KEY (manifest_id) REFERENCES manifest(id) ON DELETE CASCADE ); `; export const INIT_CARRIER = ` CREATE TABLE IF NOT EXISTS carrier ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, name TEXT NOT NULL, sort INTEGER NOT NULL DEFAULT 0, has_packages INTEGER NOT NULL DEFAULT 0, is_reverse INTEGER NOT NULL DEFAULT 0, FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE, UNIQUE (company_id, name) ); `; export const INIT_SHIPPING = ` CREATE TABLE IF NOT EXISTS shipping ( id INTEGER PRIMARY KEY AUTOINCREMENT, manifest_id INTEGER NOT NULL, "number" TEXT NOT NULL, tracking_code TEXT NULL, carrier_id INTEGER NOT NULL, "type" TEXT NOT NULL, "state" TEXT NOT NULL, FOREIGN KEY (manifest_id) REFERENCES manifest(id) ON DELETE CASCADE, FOREIGN KEY (carrier_id) REFERENCES carrier(id) ON DELETE NO ACTION ); `; export const INIT_PACKAGE = ` CREATE TABLE IF NOT EXISTS package ( id INTEGER PRIMARY KEY AUTOINCREMENT, shipping_id INTEGER NOT NULL, entityaddress_id INTEGER NOT NULL, "number" TEXT NOT NULL, "type" TEXT NOT NULL, "state" TEXT NOT NULL, details TEXT, FOREIGN KEY (shipping_id) REFERENCES shipping(id) ON DELETE CASCADE, FOREIGN KEY (entityaddress_id) REFERENCES entityaddress(id) ON DELETE NO ACTION ); `; export const INIT_ORDERSUMMARY = ` CREATE TABLE IF NOT EXISTS ordersummary ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, manifest_id INTEGER NOT NULL UNIQUE, order_number TEXT NOT NULL, order_date TEXT NOT NULL, created_at TEXT NOT NULL DEFAULT (${UTC_NOW}), entity_id INTEGER NULL, customer_name TEXT NULL, positions INTEGER NOT NULL DEFAULT 0, gross_total REAL NOT NULL DEFAULT 0, paid_total REAL NOT NULL DEFAULT 0, ordered_quantity REAL NOT NULL DEFAULT 0, shipped_quantity REAL NOT NULL DEFAULT 0, is_paid INTEGER NOT NULL DEFAULT 0, is_shipped INTEGER NOT NULL DEFAULT 0, FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE NO ACTION, FOREIGN KEY (manifest_id) REFERENCES manifest(id) ON DELETE CASCADE, FOREIGN KEY (entity_id) REFERENCES entity(id) ON DELETE SET NULL ); CREATE INDEX IF NOT EXISTS IX_ordersummary_company_date ON ordersummary (company_id, order_date DESC, manifest_id DESC); CREATE INDEX IF NOT EXISTS IX_ordersummary_company_shipped ON ordersummary (company_id, is_shipped); CREATE INDEX IF NOT EXISTS IX_ordersummary_company_paid ON ordersummary (company_id, is_paid); CREATE INDEX IF NOT EXISTS IX_ordersummary_company_number ON ordersummary (company_id, order_number); `; export const INIT_QUOTESUMMARY = ` CREATE TABLE IF NOT EXISTS quotesummary ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, manifest_id INTEGER NOT NULL UNIQUE, quote_number TEXT NOT NULL, quote_date TEXT NOT NULL, created_at TEXT NOT NULL DEFAULT (${UTC_NOW}), entity_id INTEGER NULL, customer_name TEXT NULL, positions INTEGER NOT NULL DEFAULT 0, gross_total REAL NOT NULL DEFAULT 0, total_quantity REAL NOT NULL DEFAULT 0, FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE NO ACTION, FOREIGN KEY (manifest_id) REFERENCES manifest(id) ON DELETE CASCADE, FOREIGN KEY (entity_id) REFERENCES entity(id) ON DELETE SET NULL ); CREATE INDEX IF NOT EXISTS IX_quotesummary_company_date ON quotesummary (company_id, quote_date DESC, manifest_id DESC); CREATE INDEX IF NOT EXISTS IX_quotesummary_company_number ON quotesummary (company_id, quote_number); `; export const INIT_SHIPMENTSUMMARY = ` CREATE TABLE IF NOT EXISTS shipmentsummary ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, manifest_id INTEGER NOT NULL UNIQUE, shipment_number TEXT NOT NULL, shipment_date TEXT NOT NULL, created_at TEXT NOT NULL DEFAULT (${UTC_NOW}), order_id INTEGER NULL, order_number TEXT NULL, entity_id INTEGER NULL, customer_name TEXT NULL, positions INTEGER NOT NULL DEFAULT 0, total_quantity REAL NOT NULL DEFAULT 0, package_count INTEGER NOT NULL DEFAULT 0, carrier TEXT NULL, tracking_code TEXT NULL, state TEXT NOT NULL DEFAULT 'new', FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE NO ACTION, FOREIGN KEY (manifest_id) REFERENCES manifest(id) ON DELETE CASCADE, FOREIGN KEY (entity_id) REFERENCES entity(id) ON DELETE SET NULL ); CREATE INDEX IF NOT EXISTS IX_shipmentsummary_company_date ON shipmentsummary (company_id, shipment_date DESC, manifest_id DESC); CREATE INDEX IF NOT EXISTS IX_shipmentsummary_company_number ON shipmentsummary (company_id, shipment_number); CREATE INDEX IF NOT EXISTS IX_shipmentsummary_company_state ON shipmentsummary (company_id, state); CREATE INDEX IF NOT EXISTS IX_shipmentsummary_company_order ON shipmentsummary (company_id, order_id); `; export const INIT_DELIVERYSUMMARY = ` CREATE TABLE IF NOT EXISTS deliverysummary ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, manifest_id INTEGER NOT NULL UNIQUE, delivery_number TEXT NOT NULL, external_number TEXT, delivery_date TEXT NOT NULL, created_at TEXT NOT NULL DEFAULT (${UTC_NOW}), supplier_id INTEGER NULL, supplier_name TEXT NULL, positions INTEGER NOT NULL DEFAULT 0, gross_total REAL NOT NULL DEFAULT 0, net_total REAL NOT NULL DEFAULT 0, total_quantity REAL NOT NULL DEFAULT 0, stock_positions INTEGER NOT NULL DEFAULT 0, booked_positions INTEGER NOT NULL DEFAULT 0, unbooked_positions INTEGER NOT NULL DEFAULT 0, stock_quantity REAL NOT NULL DEFAULT 0, booked_quantity REAL NOT NULL DEFAULT 0, unbooked_quantity REAL NOT NULL DEFAULT 0, is_booked INTEGER NOT NULL DEFAULT 0, FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE NO ACTION, FOREIGN KEY (manifest_id) REFERENCES manifest(id) ON DELETE CASCADE, FOREIGN KEY (supplier_id) REFERENCES entity(id) ON DELETE SET NULL ); CREATE INDEX IF NOT EXISTS IX_deliverysummary_company_date ON deliverysummary (company_id, delivery_date DESC, manifest_id DESC); CREATE INDEX IF NOT EXISTS IX_deliverysummary_company_number ON deliverysummary (company_id, delivery_number); CREATE INDEX IF NOT EXISTS IX_deliverysummary_company_booked ON deliverysummary (company_id, is_booked); CREATE INDEX IF NOT EXISTS IX_deliverysummary_company_supplier ON deliverysummary (company_id, supplier_id); `; export const INIT_ARTICLEWAREHOUSESUMMARY = ` CREATE TABLE IF NOT EXISTS articlewarehousesummary ( id INTEGER PRIMARY KEY AUTOINCREMENT, article_id INTEGER NOT NULL, warehouse_id INTEGER NOT NULL, stock REAL NOT NULL DEFAULT 0, UNIQUE (article_id, warehouse_id), FOREIGN KEY (article_id) REFERENCES article(id) ON DELETE CASCADE, FOREIGN KEY (warehouse_id) REFERENCES warehouse(id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS IX_articlewarehousesummary_warehouse ON articlewarehousesummary (warehouse_id); `; export const INIT_MCP_CLIENT = ` CREATE TABLE IF NOT EXISTS mcp_client ( id INTEGER PRIMARY KEY AUTOINCREMENT, client_id TEXT NOT NULL UNIQUE, client_secret TEXT, client_name TEXT NOT NULL, redirect_uris TEXT NOT NULL, grant_types TEXT, response_types TEXT, scope TEXT, created_at TEXT NOT NULL DEFAULT (${UTC_NOW}) ); `; export const INIT_MCP_AUTH_CODE = ` CREATE TABLE IF NOT EXISTS mcp_auth_code ( code TEXT PRIMARY KEY, client_id TEXT NOT NULL, google_auth_id INTEGER NOT NULL, redirect_uri TEXT NOT NULL, code_challenge TEXT NOT NULL, code_challenge_method TEXT NOT NULL, scope TEXT, expires_at TEXT NOT NULL, used INTEGER NOT NULL DEFAULT 0, created_at TEXT NOT NULL DEFAULT (${UTC_NOW}), FOREIGN KEY (google_auth_id) REFERENCES google_auth(id) ON DELETE CASCADE ); `; export const INIT_MCP_TOKEN = ` CREATE TABLE IF NOT EXISTS mcp_token ( id INTEGER PRIMARY KEY AUTOINCREMENT, refresh_token TEXT NOT NULL UNIQUE, client_id TEXT NOT NULL, google_auth_id INTEGER NOT NULL, scope TEXT, expires_at TEXT NOT NULL, revoked INTEGER NOT NULL DEFAULT 0, created_at TEXT NOT NULL DEFAULT (${UTC_NOW}), FOREIGN KEY (google_auth_id) REFERENCES google_auth(id) ON DELETE CASCADE ); `; export const INIT_SUBAGENTSCHEDULE = ` CREATE TABLE IF NOT EXISTS subagentschedule ( id INTEGER PRIMARY KEY AUTOINCREMENT, company_id INTEGER NOT NULL, "desc" TEXT, prompt TEXT NOT NULL, skills TEXT, lastagentnote TEXT, max_itr INTEGER NOT NULL DEFAULT 15, cron TEXT NOT NULL, created_at TEXT NOT NULL DEFAULT (${UTC_NOW}), lastrun_at TEXT, FOREIGN KEY (company_id) REFERENCES company(id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS IX_subagentschedule_company ON subagentschedule (company_id); `; export const INIT_HEALTHCHECK = ` CREATE TABLE IF NOT EXISTS healthcheck ( id INTEGER PRIMARY KEY AUTOINCREMENT, "sequence" INTEGER NOT NULL DEFAULT 0, updated_at TEXT NOT NULL DEFAULT (${UTC_NOW}) ); `; /** DDL scripts in dependency order for SQLite schema initialization. */ export const SCHEMA_SCRIPTS = [ INIT_HEALTHCHECK, INIT_META, INIT_LANGUAGE, INIT_TAX, INIT_CATEGORY, INIT_PIC, INIT_COMPANY, INIT_GOOGLE_AUTH, INIT_CUSTOMERGROUP, INIT_ENTITY, INIT_ENTITY_COMPANY_NUMBER_UQ, INIT_ENTITYADDRESS, INIT_ENTITYCONTACT, INIT_UNIT, INIT_UNITTEXT, INIT_OPTIONSLIST, INIT_ARTICLELIST, INIT_BRAND, INIT_PROPERTYNAME, INIT_ATTRIBUTENAME, INIT_ATTRIBUTEVALUE, INIT_ARTICLE, INIT_ARTICLEEAN, INIT_ARTICLEPIC, INIT_BRANDPIC, INIT_ATTRIBUTEVALUEPIC, INIT_ARTICLELISTARTICLE, INIT_OPTIONSLISTARTICLE, INIT_CATEGORYARTICLE, INIT_CATEGORYPIC, INIT_CATEGORYTEXT, INIT_ARTICLENAME, INIT_PRICE, INIT_ARTICLE_SUPPLIER, INIT_ARTICLEPROPERTY, INIT_ARTICLEATTRIBUTEVALUE, INIT_CATEGORYPROPERTY, INIT_CATEGORYATTRIBUTEVALUE, INIT_MANIFEST, INIT_MANIFESTARTICLE, INIT_WAREHOUSE, INIT_LEDGER, INIT_NUMBERS, INIT_COMPANYUSER, INIT_MODELCONVERSATION, INIT_MODELMESSAGE, INIT_MODELVFS, INIT_ARTICLEHISTORY, INIT_ARTICLETOMBSTONE, INIT_ENTITYHISTORY, INIT_COMPANYHISTORY, INIT_COMPANYSETTING, INIT_POSTERMINAL, INIT_POSTERMINALCATEGORY, INIT_PRINTER, INIT_LABELTEMPLATE, INIT_FILE, INIT_MANIFESTATTACHMENT, INIT_MANIFESTATTACHMENT_TRIGGER, INIT_ACCOUNT, INIT_PAYMENT, INIT_CARRIER, INIT_SHIPPING, INIT_PACKAGE, INIT_ORDERSUMMARY, INIT_QUOTESUMMARY, INIT_SHIPMENTSUMMARY, INIT_DELIVERYSUMMARY, INIT_ARTICLEWAREHOUSESUMMARY, INIT_MCP_CLIENT, INIT_MCP_AUTH_CODE, INIT_MCP_TOKEN, INIT_SUBAGENTSCHEDULE, ];