Phase 114 complete (v3.7 Invoices): - /settings/accounting jako hub-rozdroze (Paragony / Faktury) - /settings/accounting/receipts + /invoices osobne podstrony list i edycji - InvoiceConfigRepository + Controller (CRUD z walidacja delegacji) - Seed Domyslny VAT (NOT EXISTS idempotent) - invoice-config-form.js (toggle is_delegated -> integration_id) - confirm-delete.js (globalny modul OrderProAlerts.confirm) - Legacy aliasy starych endpointow /settings/accounting/save|toggle|delete Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
37 KiB
Database Schema
Updated: 2026-05-10 | Total tables: 59 | Engine: InnoDB | Charset: utf8mb4_unicode_ci
Auth / Users
users — System user accounts with authentication
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK, AUTO_INCREMENT |
name |
VARCHAR(120) | NO | |
email |
VARCHAR(190) | NO | UNIQUE |
password_hash |
VARCHAR(255) | NO | |
remember_token |
VARCHAR(255) | YES | SHA256 of cookie token |
created_at |
DATETIME | NO | DEFAULT CURRENT_TIMESTAMP |
Products
products — Main product catalog
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
uuid |
CHAR(36) | NO | UNIQUE |
type |
ENUM('simple','variant_parent') | NO | DEFAULT 'simple' |
sku |
VARCHAR(128) | YES | UNIQUE |
ean |
VARCHAR(32) | YES | |
status |
TINYINT(1) | NO | DEFAULT 1 |
promoted |
TINYINT(1) | NO | DEFAULT 0 |
new_to_date |
DATE | YES | |
additional_message |
TINYINT(1) | NO | DEFAULT 0 |
additional_message_required |
TINYINT(1) | NO | DEFAULT 0 |
additional_message_text |
TEXT | YES | |
vat |
DECIMAL(5,2) | YES | |
weight |
DECIMAL(10,3) | YES | |
price_brutto |
DECIMAL(12,2) | NO | DEFAULT 0.00 |
price_brutto_promo |
DECIMAL(12,2) | YES | |
price_netto |
DECIMAL(12,2) | YES | |
price_netto_promo |
DECIMAL(12,2) | YES | |
quantity |
DECIMAL(12,3) | NO | DEFAULT 0.000 |
producer_id |
INT UNSIGNED | YES | |
producer_name |
VARCHAR(255) | YES | |
product_unit_id |
INT UNSIGNED | YES | |
custom_fields_json |
TEXT | YES | |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO | ON UPDATE CURRENT_TIMESTAMP |
deleted_at |
DATETIME | YES | Soft delete |
Indexes: products_status_idx, products_type_idx, products_updated_at_idx, products_ean_idx
product_translations — Localized product names/descriptions
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
product_id |
INT UNSIGNED | NO | FK → products(id) CASCADE |
lang |
VARCHAR(8) | NO | |
name |
VARCHAR(255) | NO | |
short_description |
TEXT | YES | |
description |
LONGTEXT | YES | |
meta_title |
VARCHAR(255) | YES | |
meta_description |
VARCHAR(255) | YES | |
meta_keywords |
VARCHAR(255) | YES | |
seo_link |
VARCHAR(255) | YES | |
security_information |
MEDIUMTEXT | YES | GPSR data |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
UNIQUE: (product_id, lang)
product_images — Product image storage references
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
product_id |
INT UNSIGNED | NO | FK → products(id) CASCADE |
storage_path |
VARCHAR(255) | NO | |
alt |
VARCHAR(255) | YES | |
sort_order |
INT | NO | DEFAULT 0 |
is_main |
TINYINT(1) | NO | DEFAULT 0 |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
product_categories — Product–category associations (m2m)
| Column | Type | Notes |
|---|---|---|
product_id |
INT UNSIGNED | FK → products(id) CASCADE |
category_id |
INT UNSIGNED | |
created_at |
DATETIME |
PK: (product_id, category_id)
product_variants — Variants for variant_parent products
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
product_id |
INT UNSIGNED | NO | FK → products(id) CASCADE |
permutation_hash |
VARCHAR(191) | NO | |
sku |
VARCHAR(128) | YES | UNIQUE |
ean |
VARCHAR(32) | YES | |
status |
TINYINT(1) | NO | DEFAULT 1 |
stock_0_buy |
TINYINT(1) | NO | DEFAULT 0 |
price_brutto |
DECIMAL(12,2) | YES | |
price_netto |
DECIMAL(12,2) | YES | |
weight |
DECIMAL(10,3) | YES | |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
UNIQUE: (product_id, permutation_hash)
product_variant_attributes — Variant–attribute value mapping
| Column | Type | Notes |
|---|---|---|
variant_id |
INT UNSIGNED | FK → product_variants(id) CASCADE |
attribute_id |
INT UNSIGNED | FK → attributes(id) RESTRICT |
value_id |
INT UNSIGNED | FK → attribute_values(id) RESTRICT |
created_at |
DATETIME |
PK: (variant_id, attribute_id)
attributes — Attribute definitions (e.g., size, color)
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
type |
TINYINT UNSIGNED | NO | DEFAULT 1 |
status |
TINYINT(1) | NO | DEFAULT 1 |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
attribute_translations — Localized attribute names
| Column | Type | Notes |
|---|---|---|
attribute_id |
INT UNSIGNED | FK → attributes(id) CASCADE |
lang |
VARCHAR(8) | |
name |
VARCHAR(255) | |
created_at |
DATETIME | |
updated_at |
DATETIME |
PK: (attribute_id, lang)
attribute_values — Possible values per attribute
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
attribute_id |
INT UNSIGNED | NO | FK → attributes(id) CASCADE |
status |
TINYINT(1) | NO | DEFAULT 1 |
is_default |
TINYINT(1) | NO | DEFAULT 0 |
impact_on_price |
DECIMAL(12,2) | YES | |
sort_order |
INT | NO | DEFAULT 0 |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
attribute_value_translations — Localized value names
| Column | Type | Notes |
|---|---|---|
value_id |
INT UNSIGNED | FK → attribute_values(id) CASCADE |
lang |
VARCHAR(8) | |
name |
VARCHAR(255) | |
created_at |
DATETIME | |
updated_at |
DATETIME |
PK: (value_id, lang)
product_change_log — Audit trail for product modifications
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
product_id |
INT UNSIGNED | NO | FK → products(id) CASCADE |
user_id |
INT UNSIGNED | YES | FK → users(id) SET NULL |
change_type |
VARCHAR(64) | NO | |
before_json |
JSON | YES | |
after_json |
JSON | YES | |
created_at |
DATETIME | NO |
sales_channels — Selling channel definitions
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
code |
VARCHAR(64) | NO | UNIQUE |
name |
VARCHAR(128) | NO | |
type |
VARCHAR(64) | NO | |
status |
TINYINT(1) | NO | DEFAULT 1 |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
product_channel_map — Link products to external channel offers
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
product_id |
INT UNSIGNED | NO | FK → products(id) CASCADE |
channel_id |
INT UNSIGNED | NO | FK → sales_channels(id) CASCADE |
integration_id |
INT UNSIGNED | YES | FK → integrations(id) SET NULL |
external_product_id |
VARCHAR(128) | YES | |
external_variant_id |
VARCHAR(128) | YES | |
sync_state |
VARCHAR(32) | NO | DEFAULT 'not_linked' |
link_type |
VARCHAR(32) | NO | DEFAULT 'manual' |
link_status |
VARCHAR(32) | NO | DEFAULT 'active' |
confidence |
TINYINT UNSIGNED | YES | |
linked_at |
DATETIME | YES | |
unlinked_at |
DATETIME | YES | |
sync_meta_json |
JSON | YES | |
last_sync_at |
DATETIME | YES | |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
UNIQUE: (product_id, channel_id, external_product_id, external_variant_id)
channel_offers — External channel offer snapshots
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
integration_id |
INT UNSIGNED | NO | FK → integrations(id) CASCADE |
channel_id |
INT UNSIGNED | NO | FK → sales_channels(id) CASCADE |
external_product_id |
VARCHAR(128) | NO | |
external_variant_id |
VARCHAR(128) | YES | |
external_offer_id |
VARCHAR(128) | YES | |
name |
VARCHAR(255) | NO | |
sku |
VARCHAR(128) | YES | |
ean |
VARCHAR(32) | YES | |
price_brutto |
DECIMAL(12,2) | YES | |
quantity |
DECIMAL(12,3) | YES | |
currency |
VARCHAR(8) | YES | |
offer_status |
VARCHAR(32) | NO | DEFAULT 'active' |
source_updated_at |
DATETIME | YES | |
last_seen_at |
DATETIME | NO | |
payload_json |
JSON | YES | |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
UNIQUE: (integration_id, external_product_id, external_variant_id)
product_link_events — Audit log for product-channel linking changes
product_link_alerts — Alerts for product-channel link issues (ENUM status: active, resolved)
product_integration_translations — Integration-specific product description overrides
Orders
orders — Imported orders from sales channels
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
internal_order_number |
VARCHAR(11) | YES | UNIQUE, auto-assigned |
integration_id |
INT UNSIGNED | NO | FK → integrations(id) CASCADE |
external_order_id |
VARCHAR(64) | NO | |
external_order_number |
VARCHAR(128) | YES | |
status |
VARCHAR(64) | YES | Internal status code |
currency |
CHAR(3) | YES | |
total_gross |
DECIMAL(12,2) | YES | |
total_net |
DECIMAL(12,2) | YES | |
total_with_tax |
DECIMAL(12,2) | YES | |
total_paid |
DECIMAL(12,2) | YES | |
buyer_email |
VARCHAR(190) | YES | |
buyer_name |
VARCHAR(190) | YES | |
buyer_phone |
VARCHAR(64) | YES | |
payment_method |
VARCHAR(128) | YES | |
payment_status |
VARCHAR(64) | YES | |
external_payment_type_id |
VARCHAR(128) | YES | |
delivery_method |
VARCHAR(128) | YES | |
delivery_price |
DECIMAL(12,2) | YES | |
delivery_tracking_number |
VARCHAR(128) | YES | |
invoice_requested |
TINYINT(1) | NO | DEFAULT 0 (Phase 113-01) |
external_created_at |
DATETIME | YES | |
external_updated_at |
DATETIME | YES | |
last_status_checked_at |
DATETIME | YES | |
payload_json |
JSON | YES | Full raw API payload |
fetched_at |
DATETIME | NO | |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
UNIQUE: (integration_id, external_order_id)
Note: Order notes are stored in the separate
order_notestable (nonotescolumn onorders).
order_items — Line items within orders
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
order_id |
INT UNSIGNED | NO | FK → orders(id) CASCADE |
external_item_id |
VARCHAR(64) | YES | |
name |
VARCHAR(255) | NO | |
sku |
VARCHAR(128) | YES | |
ean |
VARCHAR(64) | YES | |
quantity |
DECIMAL(12,3) | NO | DEFAULT 0 |
price_gross |
DECIMAL(12,2) | YES | |
price_net |
DECIMAL(12,2) | YES | |
vat |
DECIMAL(6,2) | YES | |
personalization |
TEXT | YES | Customer personalization data for design generation |
project_generated |
TINYINT(1) | NO | DEFAULT 0 |
project_generated_at |
DATETIME | YES | |
payload_json |
JSON | YES | |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
order_activity_log — Event log for order state changes
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
BIGINT UNSIGNED | NO | PK |
order_id |
BIGINT UNSIGNED | NO | FK → orders(id) CASCADE |
event_type |
VARCHAR(32) | NO | |
summary |
VARCHAR(255) | NO | |
details_json |
JSON | YES | |
actor_type |
VARCHAR(16) | NO | DEFAULT 'system' |
actor_name |
VARCHAR(128) | YES | |
created_at |
DATETIME | NO |
order_payments — Payments linked to orders
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
order_id |
INT UNSIGNED | NO | FK → orders(id) CASCADE |
source_payment_id |
VARCHAR(64) | YES | |
external_payment_id |
VARCHAR(64) | YES | |
payment_type_id |
VARCHAR(64) | NO | |
payment_date |
DATETIME | YES | |
amount |
DECIMAL(12,2) | YES | |
currency |
CHAR(3) | YES | |
comment |
VARCHAR(255) | YES | |
payload_json |
JSON | YES | |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
UNIQUE: (order_id, source_payment_id)
Order Statuses
order_status_groups — Status group categories (e.g., "Nowe", "W realizacji")
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
name |
VARCHAR(120) | NO | |
code |
VARCHAR(64) | NO | UNIQUE |
color_hex |
CHAR(7) | NO | DEFAULT '#64748b' |
sort_order |
INT | NO | DEFAULT 0 |
is_active |
TINYINT(1) | NO | DEFAULT 1 |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
order_statuses — Individual statuses within groups
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
group_id |
INT UNSIGNED | NO | FK → order_status_groups(id) CASCADE |
name |
VARCHAR(120) | NO | |
code |
VARCHAR(64) | NO | UNIQUE |
sort_order |
INT | NO | DEFAULT 0 |
is_active |
TINYINT(1) | NO | DEFAULT 1 |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
order_status_mappings — Map external (e.g., shopPRO) statuses to internal ones
| Column | Type | Notes |
|---|---|---|
id |
INT UNSIGNED | PK |
integration_id |
INT UNSIGNED | FK → integrations(id) CASCADE |
shoppro_status_code |
VARCHAR(64) | |
shoppro_status_name |
VARCHAR(128) | |
orderpro_status_code |
VARCHAR(64) | |
created_at |
DATETIME | |
updated_at |
DATETIME |
UNIQUE: (integration_id, shoppro_status_code)
integration_order_sync_state — Track order fetch progress per integration
integration_order_status_sync_state — Track status sync progress per integration and direction
Shipments & Delivery
shipment_packages — Prepared shipments with tracking
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
BIGINT UNSIGNED | NO | PK |
order_id |
BIGINT UNSIGNED | NO | FK → orders(id) CASCADE |
provider |
VARCHAR(32) | NO | DEFAULT 'allegro_wza' |
delivery_method_id |
VARCHAR(128) | YES | |
credentials_id |
VARCHAR(128) | YES | |
command_id |
VARCHAR(64) | YES | |
shipment_id |
VARCHAR(64) | YES | |
tracking_number |
VARCHAR(128) | YES | |
status |
VARCHAR(32) | NO | DEFAULT 'draft' |
delivery_status |
VARCHAR(32) | NO | DEFAULT 'unknown' |
delivery_status_raw |
VARCHAR(128) | YES | Provider's original status string |
delivery_status_updated_at |
DATETIME | YES | |
carrier_id |
VARCHAR(64) | YES | |
package_type |
VARCHAR(16) | NO | DEFAULT 'PACKAGE' |
weight_kg |
DECIMAL(8,3) | YES | |
length_cm |
DECIMAL(8,1) | YES | |
width_cm |
DECIMAL(8,1) | YES | |
height_cm |
DECIMAL(8,1) | YES | |
insurance_amount |
DECIMAL(12,2) | YES | |
cod_amount |
DECIMAL(12,2) | YES | |
label_format |
VARCHAR(8) | NO | DEFAULT 'PDF' |
label_path |
VARCHAR(512) | YES | |
receiver_point_id |
VARCHAR(64) | YES | Parcel locker ID |
sender_point_id |
VARCHAR(64) | YES | |
reference_number |
VARCHAR(128) | YES | |
error_message |
TEXT | YES | |
payload_json |
JSON | YES | |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
Indexes: shipment_packages_order_idx, shipment_packages_status_idx, shipment_packages_tracking_idx, idx_delivery_status
shipment_presets — Predefined shipment configurations (saved templates)
| Column | Type | Notes |
|---|---|---|
id |
BIGINT UNSIGNED | PK |
name |
VARCHAR(100) | |
color |
VARCHAR(7) | DEFAULT '#3b82f6' |
carrier |
VARCHAR(32) | |
provider_code |
VARCHAR(32) | |
delivery_method_id |
VARCHAR(128) | |
credentials_id |
VARCHAR(128) | DEFAULT '' |
carrier_id |
VARCHAR(64) | DEFAULT '' |
package_type |
VARCHAR(16) | DEFAULT 'PACKAGE' |
length_cm |
DECIMAL(8,1) | DEFAULT 25.0 |
width_cm |
DECIMAL(8,1) | DEFAULT 20.0 |
height_cm |
DECIMAL(8,1) | DEFAULT 8.0 |
weight_kg |
DECIMAL(8,3) | DEFAULT 1.000 |
sender_point_id |
VARCHAR(64) | DEFAULT '' |
label_format |
VARCHAR(8) | DEFAULT 'PDF' |
sort_order |
INT UNSIGNED | DEFAULT 0 |
created_at |
TIMESTAMP | |
updated_at |
TIMESTAMP |
delivery_statuses — Normalized delivery status definitions (Phase 108)
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
key |
VARCHAR(50) | NO | UNIQUE |
label_pl |
VARCHAR(100) | NO | Polish label |
color |
VARCHAR(7) | NO | DEFAULT '#6c757d' |
sort_order |
TINYINT UNSIGNED | NO | DEFAULT 0 |
is_terminal |
TINYINT(1) | NO | DEFAULT 0 — marks final states |
is_system |
TINYINT(1) | NO | DEFAULT 0 — system-managed |
created_at |
DATETIME | NO |
delivery_status_mappings — Map provider-specific raw statuses to normalized keys (Phase 108)
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
provider |
VARCHAR(32) | NO | |
raw_status |
VARCHAR(64) | NO | |
normalized_status |
VARCHAR(32) | NO | FK ref → delivery_statuses.key |
description |
VARCHAR(255) | NO | DEFAULT '' |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
UNIQUE: (provider, raw_status)
Integrations
integrations — Integration configurations for external services
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
type |
VARCHAR(32) | NO | e.g., 'allegro', 'shoppro', 'apaczka', 'inpost' |
name |
VARCHAR(128) | NO | |
base_url |
VARCHAR(255) | NO | |
api_key_encrypted |
TEXT | YES | AES-encrypted |
timeout_seconds |
SMALLINT UNSIGNED | NO | DEFAULT 10 |
is_active |
TINYINT(1) | NO | DEFAULT 1 |
orders_fetch_enabled |
TINYINT(1) | NO | DEFAULT 0 |
orders_fetch_start_date |
DATE | YES | |
order_status_sync_direction |
VARCHAR(32) | NO | DEFAULT 'shoppro_to_orderpro' |
last_test_status |
VARCHAR(16) | YES | |
last_test_http_code |
SMALLINT UNSIGNED | YES | |
last_test_message |
VARCHAR(255) | YES | |
last_test_at |
DATETIME | YES | |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
UNIQUE: (type, name)
integration_test_logs — API test results log
allegro_integration_settings — Allegro OAuth tokens and API config
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
integration_id |
INT UNSIGNED | YES | UNIQUE, FK → integrations(id) CASCADE |
environment |
VARCHAR(16) | NO | DEFAULT 'sandbox' |
client_id |
VARCHAR(128) | YES | |
client_secret_encrypted |
TEXT | YES | |
redirect_uri |
VARCHAR(255) | YES | |
orders_fetch_enabled |
TINYINT(1) | NO | DEFAULT 0 |
orders_fetch_start_date |
DATE | YES | |
access_token_encrypted |
MEDIUMTEXT | YES | AES-encrypted |
refresh_token_encrypted |
MEDIUMTEXT | YES | AES-encrypted |
token_type |
VARCHAR(32) | YES | |
token_scope |
VARCHAR(255) | YES | |
token_expires_at |
DATETIME | YES | |
connected_at |
DATETIME | YES | |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
allegro_order_status_mappings — Allegro status → internal status
| Column | Type | Notes |
|---|---|---|
id |
INT UNSIGNED | PK |
allegro_status_code |
VARCHAR(64) | UNIQUE |
allegro_status_name |
VARCHAR(120) | |
orderpro_status_code |
VARCHAR(64) | |
created_at |
DATETIME | |
updated_at |
DATETIME |
allegro_delivery_method_mappings — Map order delivery method strings to Allegro services
| Column | Type | Notes |
|---|---|---|
id |
INT UNSIGNED | PK |
order_delivery_method |
VARCHAR(200) | UNIQUE |
allegro_delivery_method_id |
VARCHAR(128) | |
allegro_credentials_id |
VARCHAR(128) | |
allegro_carrier_id |
VARCHAR(128) | |
allegro_service_name |
VARCHAR(255) | |
created_at |
DATETIME | |
updated_at |
DATETIME |
apaczka_integration_settings — Apaczka API credentials
| Column | Type | Notes |
|---|---|---|
id |
TINYINT UNSIGNED | PK (fixed 1 row) |
integration_id |
INT UNSIGNED | UNIQUE, FK → integrations(id) |
api_key_encrypted |
TEXT | |
created_at |
DATETIME | |
updated_at |
DATETIME |
inpost_integration_settings — InPost ShipX settings
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
TINYINT UNSIGNED | NO | PK (fixed 1 row) |
integration_id |
INT UNSIGNED | YES | UNIQUE, FK → integrations(id) |
api_token_encrypted |
TEXT | YES | |
organization_id |
VARCHAR(50) | YES | |
environment |
ENUM('sandbox','production') | NO | DEFAULT 'sandbox' |
default_dispatch_method |
ENUM('pop','parcel_locker','courier') | NO | DEFAULT 'pop' |
default_dispatch_point |
VARCHAR(50) | YES | |
default_insurance |
DECIMAL(10,2) | YES | |
default_locker_size |
ENUM('small','medium','large') | NO | DEFAULT 'small' |
default_courier_length |
SMALLINT UNSIGNED | YES | DEFAULT 20 |
default_courier_width |
SMALLINT UNSIGNED | YES | DEFAULT 15 |
default_courier_height |
SMALLINT UNSIGNED | YES | DEFAULT 8 |
label_format |
ENUM('Pdf','Zpl','Epl') | NO | DEFAULT 'Pdf' |
weekend_delivery |
TINYINT(1) | NO | DEFAULT 0 |
auto_insurance_value |
TINYINT(1) | NO | DEFAULT 0 |
multi_parcel |
TINYINT(1) | NO | DEFAULT 0 |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
fakturownia_integration_settings — Fakturownia account credentials (Phase 113-01; multi-account via integration_id)
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
integration_id |
INT UNSIGNED | NO | UNIQUE, FK → integrations(id) CASCADE |
account_prefix |
VARCHAR(64) | NO | Subdomain: {prefix}.fakturownia.pl |
api_token_encrypted |
TEXT | YES | AES-encrypted via IntegrationSecretCipher |
department_id |
VARCHAR(64) | YES | Optional Fakturownia department |
default_kind |
VARCHAR(32) | NO | DEFAULT 'vat' |
default_payment_to_days |
TINYINT UNSIGNED | NO | DEFAULT 7 |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
UNIQUE: (integration_id) — one settings row per Fakturownia integration. Multiple integrations of type='fakturownia' allowed.
Accounting / Receipts
receipt_configs — Receipt generation configurations
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
name |
VARCHAR(128) | NO | |
is_active |
TINYINT(1) | NO | DEFAULT 1 |
number_format |
VARCHAR(64) | NO | DEFAULT 'PAR/%N/%M/%Y' |
numbering_type |
ENUM('monthly','yearly') | NO | DEFAULT 'monthly' |
is_named |
TINYINT(1) | NO | DEFAULT 0 |
sale_date_source |
ENUM('order_date','payment_date','issue_date') | NO | DEFAULT 'issue_date' |
order_reference |
ENUM('none','orderpro','integration') | NO | DEFAULT 'none' |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
receipts — Generated receipts / invoices
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
order_id |
BIGINT UNSIGNED | NO | FK → orders(id) CASCADE |
config_id |
INT UNSIGNED | NO | FK → receipt_configs(id) RESTRICT |
receipt_number |
VARCHAR(64) | NO | UNIQUE |
issue_date |
DATETIME | NO | |
sale_date |
DATETIME | NO | |
seller_data_json |
JSON | NO | Snapshot of company data at issue time |
buyer_data_json |
JSON | YES | |
items_json |
JSON | NO | |
total_net |
DECIMAL(12,2) | NO | DEFAULT 0.00 |
total_gross |
DECIMAL(12,2) | NO | DEFAULT 0.00 |
order_reference_value |
VARCHAR(128) | YES | |
created_by |
INT UNSIGNED | YES | |
created_at |
DATETIME | NO |
receipt_number_counters — Sequential numbering per config/period
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
config_id |
INT UNSIGNED | NO | FK → receipt_configs(id) CASCADE |
year |
SMALLINT UNSIGNED | NO | |
month |
TINYINT UNSIGNED | YES | NULL for yearly numbering |
last_number |
INT UNSIGNED | NO | DEFAULT 0 |
UNIQUE: (config_id, year, month)
Invoices (Phase 113-01)
Seed (Phase 114-01): migration
20260511_000107_seed_default_invoice_config.sqlinserts a defaultDomyslny VATconfig (formatFV/%N/%M/%Y, monthly numbering,is_delegated=0,payment_to_days=7) idempotently viaNOT EXISTSguard.
invoice_configs — Invoice generation configurations (analogous to receipt_configs plus delegation flag)
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
name |
VARCHAR(128) | NO | |
integration_id |
INT UNSIGNED | YES | FK → integrations(id) SET NULL — points to Fakturownia account when delegated |
is_delegated |
TINYINT(1) | NO | DEFAULT 0 — when 1, invoice creation calls Fakturownia API |
is_active |
TINYINT(1) | NO | DEFAULT 1 |
number_format |
VARCHAR(64) | NO | DEFAULT 'FV/%N/%M/%Y' |
numbering_type |
ENUM('monthly','yearly') | NO | DEFAULT 'monthly' |
sale_date_source |
ENUM('order_date','payment_date','issue_date') | NO | DEFAULT 'issue_date' |
order_reference |
ENUM('none','orderpro','integration') | NO | DEFAULT 'none' |
payment_to_days |
TINYINT UNSIGNED | NO | DEFAULT 7 |
default_kind |
VARCHAR(32) | NO | DEFAULT 'vat' (vat/proforma/etc) |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
invoices — Generated invoices (snapshot pattern like receipts, plus external linkage when delegated)
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
order_id |
BIGINT UNSIGNED | NO | FK → orders(id) CASCADE |
config_id |
INT UNSIGNED | NO | FK → invoice_configs(id) RESTRICT |
invoice_number |
VARCHAR(64) | NO | UNIQUE |
issue_date |
DATETIME | NO | |
sale_date |
DATETIME | NO | |
payment_due_date |
DATETIME | YES | |
seller_data_json |
JSON | NO | Snapshot of company data at issue time |
buyer_data_json |
JSON | YES | |
items_json |
JSON | NO | |
total_net |
DECIMAL(12,2) | NO | DEFAULT 0.00 |
total_gross |
DECIMAL(12,2) | NO | DEFAULT 0.00 |
order_reference_value |
VARCHAR(128) | YES | |
external_invoice_id |
VARCHAR(128) | YES | Fakturownia invoice id when delegated |
external_pdf_url |
VARCHAR(500) | YES | URL returned by Fakturownia |
kind |
VARCHAR(32) | NO | DEFAULT 'vat' |
created_by |
INT UNSIGNED | YES | |
created_at |
DATETIME | NO |
Indexes: invoices_number_unique, invoices_order_idx, invoices_config_date_idx (config_id, issue_date), invoices_external_idx
invoice_number_counters — Sequential numbering per config/period (mirrors receipt_number_counters)
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
config_id |
INT UNSIGNED | NO | FK → invoice_configs(id) CASCADE |
year |
SMALLINT UNSIGNED | NO | |
month |
TINYINT UNSIGNED | YES | NULL for yearly numbering |
last_number |
INT UNSIGNED | NO | DEFAULT 0 |
UNIQUE: (config_id, year, month)
email_mailboxes — SMTP mailbox configurations
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
name |
VARCHAR(100) | NO | |
smtp_host |
VARCHAR(255) | NO | |
smtp_port |
SMALLINT UNSIGNED | NO | DEFAULT 587 |
smtp_encryption |
ENUM('tls','ssl','none') | NO | DEFAULT 'tls' |
smtp_username |
VARCHAR(255) | NO | |
smtp_password_encrypted |
TEXT | NO | AES-encrypted |
sender_email |
VARCHAR(255) | NO | |
sender_name |
VARCHAR(200) | YES | |
html_layout |
LONGTEXT | YES | Wrapper HTML for all emails from this mailbox |
is_default |
TINYINT(1) | NO | DEFAULT 0 |
is_active |
TINYINT(1) | NO | DEFAULT 1 |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
email_templates — Email message templates with variable placeholders
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
name |
VARCHAR(200) | NO | |
subject |
VARCHAR(500) | NO | |
body_html |
TEXT | NO | Supports {{variable}} placeholders |
mailbox_id |
INT UNSIGNED | YES | FK → email_mailboxes(id) SET NULL |
attachment1 |
LONGTEXT | YES | |
is_active |
TINYINT(1) | NO | DEFAULT 1 |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
email_logs — Sent email history
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
BIGINT UNSIGNED | NO | PK |
template_id |
INT UNSIGNED | YES | FK → email_templates(id) SET NULL |
mailbox_id |
INT UNSIGNED | YES | FK → email_mailboxes(id) SET NULL |
order_id |
INT UNSIGNED | YES | |
recipient_email |
VARCHAR(255) | NO | |
recipient_name |
VARCHAR(200) | YES | |
subject |
VARCHAR(500) | NO | |
body_html |
TEXT | NO | |
attachments_json |
JSON | YES | |
status |
ENUM('sent','failed','pending') | NO | DEFAULT 'pending' |
error_message |
TEXT | YES | |
sent_at |
DATETIME | YES | |
created_at |
DATETIME | NO |
Automation
automation_rules — Business rules for order event automation
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
name |
VARCHAR(128) | NO | |
event_type |
VARCHAR(64) | NO | e.g., 'order_status_changed', 'order_status_aged' |
is_active |
TINYINT(1) | NO | DEFAULT 1 |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
Index: (event_type, is_active)
automation_conditions — Conditions for automation rules
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
rule_id |
INT UNSIGNED | NO | FK → automation_rules(id) CASCADE |
condition_type |
VARCHAR(64) | NO | |
condition_value |
JSON | NO | |
sort_order |
SMALLINT UNSIGNED | NO | DEFAULT 0 |
automation_actions — Actions executed when rules trigger
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
rule_id |
INT UNSIGNED | NO | FK → automation_rules(id) CASCADE |
action_type |
VARCHAR(64) | NO | e.g., 'send_email', 'update_status', 'create_receipt' |
action_config |
JSON | NO | |
sort_order |
SMALLINT UNSIGNED | NO | DEFAULT 0 |
automation_execution_logs — Audit log for rule executions
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
BIGINT UNSIGNED | NO | PK |
event_type |
VARCHAR(64) | NO | |
rule_id |
INT UNSIGNED | YES | FK → automation_rules(id) SET NULL |
rule_name |
VARCHAR(128) | NO | Snapshot at execution time |
order_id |
INT UNSIGNED | NO | FK → orders(id) CASCADE |
execution_status |
VARCHAR(16) | NO | |
result_message |
VARCHAR(500) | YES | |
context_json |
JSON | YES | |
executed_at |
DATETIME | NO | |
created_at |
DATETIME | NO |
automation_email_once_deliveries — Idempotency guard: email sent-once per rule+action+order (Phase 107)
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
BIGINT UNSIGNED | NO | PK |
rule_id |
INT UNSIGNED | NO | FK → automation_rules(id) CASCADE |
action_id |
INT UNSIGNED | NO | FK → automation_actions(id) CASCADE |
order_id |
BIGINT UNSIGNED | NO | FK → orders(id) CASCADE |
created_at |
DATETIME | NO |
UNIQUE: (rule_id, action_id, order_id)
Print Queue
print_api_keys — API keys for remote print client authentication
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT | NO | PK |
name |
VARCHAR(128) | NO | |
key_hash |
VARCHAR(128) | NO | UNIQUE, SHA256 |
key_prefix |
VARCHAR(8) | NO | Shown in UI for identification |
is_active |
TINYINT(1) | NO | DEFAULT 1 |
last_used_at |
DATETIME | YES | |
created_at |
DATETIME | NO |
print_jobs — Print queue for remote label printing
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
order_id |
BIGINT UNSIGNED | NO | |
package_id |
BIGINT UNSIGNED | NO | |
label_path |
VARCHAR(255) | NO | |
status |
ENUM('pending','printing','completed','failed') | NO | DEFAULT 'pending' |
created_by |
INT UNSIGNED | NO | |
created_at |
DATETIME | NO | |
completed_at |
DATETIME | YES |
Cron & Scheduling
cron_jobs — Individual cron job queue entries
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
job_type |
VARCHAR(80) | NO | |
status |
ENUM('pending','processing','completed','failed','cancelled') | NO | DEFAULT 'pending' |
priority |
TINYINT UNSIGNED | NO | DEFAULT 100 |
payload |
JSON | YES | |
result |
JSON | YES | |
attempts |
SMALLINT UNSIGNED | NO | DEFAULT 0 |
max_attempts |
SMALLINT UNSIGNED | NO | DEFAULT 3 |
last_error |
VARCHAR(500) | YES | |
scheduled_at |
DATETIME | NO | |
started_at |
DATETIME | YES | |
completed_at |
DATETIME | YES | |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
Index: (status, priority, scheduled_at)
cron_schedules — Recurring job definitions
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
job_type |
VARCHAR(80) | NO | UNIQUE |
interval_seconds |
INT UNSIGNED | NO | |
priority |
TINYINT UNSIGNED | NO | DEFAULT 100 |
max_attempts |
SMALLINT UNSIGNED | NO | DEFAULT 3 |
payload |
JSON | YES | |
enabled |
TINYINT(1) | NO | DEFAULT 1 |
last_run_at |
DATETIME | YES | |
next_run_at |
DATETIME | YES | |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
Settings & Configuration
app_settings — Global key-value configuration store
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
setting_key |
VARCHAR(120) | NO | UNIQUE |
setting_value |
TEXT | YES | |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
Default keys: cron_run_on_web, cron_web_limit, gs1_api_login, gs1_prefix, products_sku_format
company_settings — Single-record seller/company configuration (always id=1)
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
TINYINT UNSIGNED | NO | PK, always 1 |
company_name |
VARCHAR(200) | YES | |
person_name |
VARCHAR(200) | YES | |
street |
VARCHAR(200) | YES | |
city |
VARCHAR(128) | YES | |
postal_code |
VARCHAR(16) | YES | |
country_code |
CHAR(2) | NO | DEFAULT 'PL' |
phone |
VARCHAR(64) | YES | |
email |
VARCHAR(128) | YES | |
tax_number |
VARCHAR(64) | YES | NIP |
bank_account |
VARCHAR(64) | YES | |
bank_owner_name |
VARCHAR(200) | YES | |
contact_person_first_name |
VARCHAR(100) | YES | |
contact_person_last_name |
VARCHAR(100) | YES | |
contact_person_phone |
VARCHAR(64) | YES | |
contact_person_email |
VARCHAR(128) | YES | |
default_package_length_cm |
DECIMAL(8,1) | NO | DEFAULT 25.0 |
default_package_width_cm |
DECIMAL(8,1) | NO | DEFAULT 20.0 |
default_package_height_cm |
DECIMAL(8,1) | NO | DEFAULT 8.0 |
default_package_weight_kg |
DECIMAL(8,3) | NO | DEFAULT 1.000 |
default_label_format |
VARCHAR(8) | NO | DEFAULT 'PDF' |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
Design Generation
project_mappings — Map product name patterns to graphic generation scripts
| Column | Type | Nullable | Notes |
|---|---|---|---|
id |
INT UNSIGNED | NO | PK |
product_name_pattern |
VARCHAR(255) | NO | Pattern matched against order_items.name |
script_name |
VARCHAR(255) | NO | Script filename in tools/generowanie/ |
output_dir |
VARCHAR(500) | YES | |
is_active |
TINYINT(1) | NO | DEFAULT 1 |
created_at |
DATETIME | NO | |
updated_at |
DATETIME | NO |
Schema Characteristics
| Property | Value |
|---|---|
| Engine | InnoDB (all tables) |
| Charset | utf8mb4_unicode_ci |
| Encrypted columns | *_encrypted suffix — AES via IntegrationSecretCipher |
| Soft deletes | products.deleted_at only |
| Audit via JSON | payload_json snapshots in orders, shipments, receipts |
| Migrations | database/migrations/YYYYMMDD_NNNNNN_description.sql |
| Deferred indexes | idx_order_addresses_order_type, idx_shipment_packages_order_delivery — apply at >50k orders |
Reporting Usage
Statistics Summary (/statistics/summary) — no dedicated reporting tables.
- Reads existing
ordersrows and groups by month using the same effective order date used by/statistics/orders. - Default summary history starts at April 2026 (
2026-04-01), even if older rows exist. - Splits series by channel key: Allegro as one series and each shopPRO integration by
orders.integration_id. - Uses
integrations.nameonly for display labels when available. - Filters by selected status groups through
order_status_groupsandorder_statuses. - Uses existing gross amount columns via
OrdersStatisticsRepository::grossAmountSql(). - No schema migration was introduced for Phase 110.