Back to Modules

TEKNIK — THE FOUNDATION MODULE

Everything downstream depends on this. No order, no production, no test can exist without data defined here.

February 2026 • Solen Kablo • Living Document

Teknik is where a cable is born. Before a single meter of wire is drawn, before a customer order is placed, before a test can be assigned — someone has to define what cables the factory can produce, what machines exist, what parameters those machines accept, what standards the cables must pass, and what gets printed on them. Teknik holds all of this. It is the single source of truth that every other module reads from but never writes to.

6
SUBMODULES
~75
API ENDPOINTS
12
DATABASE TABLES
4000+
LINES OF FRONTEND

TABLE OF CONTENTS

1. What Teknik Does 2. The Data Flow 3. The Database Layer 4. The Backend Architecture 5. The Frontend 6. The Submodules 6.1 Machine Management 6.2 Standards Management 6.3 Operator Management 6.4 Markalama (Cable Marking) 6.5 & 6.6 Kablo Tasarım & Kablo Veritabanı 7. Conclusion

1. WHAT TEKNIK DOES

The Teknik module answers five questions that the entire factory depends on:

  1. What cables can we produce? — Cable Playground designs them. Cable Database stores the approved results. Every cable is defined as an ordered sequence of machine steps with exact parameters.
  2. What machines do we have? — Machine Management registers all 7 machine types with their physical capabilities (speed ranges, diameter limits, thickness ranges). The Playground uses these to validate that a design is physically producible.
  3. What quality standards must be met? — Standards Management defines every test (IEC-EN, UL, SLN) with parameters, pass/fail criteria, and test frequencies. These are linked to cable designs — each design knows exactly which tests it requires at which production step.
  4. What gets printed on the cable? — Markalama defines the ordered word arrays that the extruder prints during production (company name, standard, voltage, cross-section, etc.).
  5. Who operates the machines? — Operator Management maintains the registry of production operators who are assigned to sessions.

Zero dependencies. Teknik depends on no other business module. It reads only from the users table (for created_by tracking). Every other module — Sipariş, Üretim, Lab, Stok — depends on Teknik. This makes it the foundation layer of the entire system.

2. THE DATA FLOW

Data flows in one direction: from Teknik outward. Here is how each submodule feeds the rest of the system.

MACHINES
Define capabilities
PLAYGROUND
Design cables
CABLE DB
Store approved
ORDERS
Select cables
STANDARDS
Define tests
PLAYGROUND
Assign to steps
CABLE DB
Store requirements
LAB
Execute tests

The Cable Database is the convergence point. It stores the finalized design as structured JSON: the complete production flow, every half-product that will be created, the bill of raw materials, and all test requirements. When Sipariş calculates material needs or Üretim generates work cards, they read from Cable Database — never from the Playground or Machines directly.

3. THE DATABASE LAYER

12 tables serve the Teknik module. They fall into four groups:

Machine Tables (7)

One table per machine type. Each stores the physical capabilities of that machine as min/max/increment ranges. The system generates dropdown options by stepping through these ranges.

TableUnique ConfigInput Code
kabatel_cekme_machinesspeed, tav (anneal current), output diameterA
kalaylama_machinesspeed, tin thickness (μm)X
incetel_cekme_machinesspeed, input count, output diameter, tav
buncher_machinesspeed, hatve (lay length), input countZ,T,U
extruder_machinesspeed, insulation thickness, sheath thicknessT,Z
ebeam_machinesspeed, radiation level (kGy)
aktarma_machines(brand/model only)

Every configurable parameter has a database-level CHECK constraint: max > min, increment > 0, min ≥ 0. This means invalid machine configurations are impossible to save — the database itself enforces physical sanity.

Design Tables (3)

TablePurposeKey Fields
cable_designsDesign sessions from the Playgrounddesign_code (unique), standard (EN/UL/SLN), cross_section, design_data (JSON)
design_stepsIndividual production steps within a designstep_number, machine_type, configuration (JSON), inputs/outputs (JSON), tests (JSON)
cable_databaseFinalized, approved cable definitionscable_code (unique), production_flow (JSON), half_products (JSON), raw_materials (JSON), test_requirements (JSON)

The relationship: CableDesign → many DesignStep (cascade delete) → one CableDatabase entry on finalize. The Cable Database stores everything as denormalized JSON blobs — intentionally. When the Material Calculator needs to compute copper requirements for an order, it reads one row from cable_database and has the complete production flow without any joins.

Quality Tables (2)

TablePurposeKey Fields
test_standardsTest definitionsstandard_category (IEC-EN/UL/SLN), test_name, standard_number, test_samples
test_parametersParameters within a testparameter_name, parameter_unit, parameter_order, is_required

A test standard has N parameters (cascade delete). When a test is assigned to a design step in the Playground, the standard ID and frequency (start/end/every reel) are embedded in the step’s JSON. This means the Cable Database carries the complete test map — Lab knows exactly what to test and when, without querying Teknik at production time.

Supporting Tables

TablePurpose
product_codesSHA-256 hashed product identifiers for stock deduplication. system_code (human-readable, e.g. BN_73X030) + spec_hash (deterministic hash of specifications). Ensures identical products across different designs share the same stock pool.
markingsCable printing templates. name (unique) + words (JSON array of strings). Each order-cable references a marking.
production_operatorsOperator registry. name (unique). Referenced by production sessions.

4. THE BACKEND ARCHITECTURE

The Teknik backend is split into 6 route files mounted under /api/teknik/ and 6 utility modules that power the Playground’s simulation engine.

Route Files

FilePrefixEndpointsResponsibility
machine_routes.py/teknik/machines~45CRUD + options for 7 machine types
design_routes.py/teknik/design~22Playground sessions, steps, config, undo/redo, finalize
cable_database_routes.py/teknik/cable-database~15Approved cables, product codes, analytics
standards_routes.py/teknik/standards~12Test standards, parameters, results
marking_routes.py/markings~6Marking template CRUD
operator_routes.py/operators~4Operator CRUD

Playground Engine (6 utility modules)

The Cable Playground is not a simple CRUD page — it is a real-time simulation engine that runs entirely in-memory on the backend. These are the modules that make it work:

Session Manager

In-memory session storage. Each design session has a unique ID, a step counter, undo/redo stacks (max 50 states), autosave timer (default 30s), and checkpoint/restore for atomic transactions.

Progression Engine

Tracks what exists after each step. Items have codes, quantities, statuses (active/consumed). Each machine type has its own processing function that consumes inputs and produces outputs with correct codes (e.g., BN_73X030).

Form Integration

Populates frontend dropdowns from database + current progression state. Filters available inputs per machine type (e.g., Buncher only sees Z/T/U coded items). Validates quantities before configuration.

DB Integration

Reads real machine tables. Calculates capability intersection when multiple machines are selected — returns only parameter values ALL selected machines can produce.

Validation Engine

Two validators: MachineValidator checks configs against machine ranges. ProductionFlowValidator checks step sequences, parallel groups, and test assignments.

Code Generator

Deterministic product code generation. SHA-256 spec hashing for stock deduplication. Human-readable system codes (e.g., KC_18 for 1.8mm Kabatel wire). Final cable codes encode standard, cross-section, structure, and layer thicknesses.

5. THE FRONTEND

7 pages under /teknik/*, protected by the canTeknik access flag. All pages use Ant Design Pro’s ProTable with Turkish locale, client-side search, and blurred backdrop modals.

RoutePageLinesComplexity
/teknik/dashboardDashboard~400Stats, quick actions, recent designs
/teknik/playgroundCable Playground~4,300SVG canvas, 6 config forms, 3 view modes, undo/redo, autosave
/teknik/cable-databaseCable Database~690Table + detail drawer with 3 tabs
/teknik/machinesMachine Management~7307 machine tabs, dynamic forms
/teknik/standardsStandards~550Standards CRUD + parameter forms
/teknik/markalamaMarkalama~370Marking templates with word arrays
/teknik/operator-yonetimiOperators~280Simple name CRUD

The Cable Playground alone accounts for more than half the frontend code. It is built as a modular component system: a usePlayground hook manages state and API calls, FlowCanvas renders the SVG diagram, MachineLibrary is the sidebar palette, ConfigurationDrawer holds 6 machine-specific forms (1,215 lines), and ProgressionPanel shows real-time material tracking.

6. THE SUBMODULES

The sections that follow document each submodule in full detail — every form field, every API endpoint, every database column, every validation rule, and the design decisions behind them. Ordered from foundational data to the tools that consume it.

6.1

Machine Management

CRUD for all 7 factory machine types. Each type has a unique configuration schema with min/max/increment ranges. The Playground reads these to validate that designs are physically producible.

~45 ENDPOINTS 7 MACHINE TYPES DB CHECK CONSTRAINTS
6.2

Standards Management

Test standard definitions with dynamic parameters, pass/fail criteria, and test frequency rules. Linked to cable designs at the step level — the Lab module reads these to know what to test and when.

12 ENDPOINTS 3 CATEGORIES DYNAMIC PARAMETERS
6.3

Operator Management

Production operator registry. Operators are assigned to production sessions by the person starting the session — they don’t need system logins. Simple name CRUD with uniqueness constraint.

4 ENDPOINTS SIMPLE CRUD
6.4

Markalama (Cable Marking)

Marking templates define the text printed on cables during extrusion. Stored as ordered word arrays with variable support ({CABLE_SIZE}, {YEAR}, etc.). Each order-cable references a marking template.

6 ENDPOINTS WORD ARRAYS VARIABLES
6.5

Cable Playground

The visual cable design workshop. Drag machines onto a canvas, configure parameters, watch the production flow build in real-time. Session-based, in-memory simulation with undo/redo, autosave, and three view modes. Where all foundational data — machines, standards, operators, markings — converges into a cable design.

22 ENDPOINTS 4,300 LOC 6 UTILITY MODULES SVG CANVAS
6.6

Cable Database

The library of approved cable designs. Each entry stores the complete production flow, half-product tree, bill of materials, and test requirements as structured JSON. The single source of truth for Orders and Production.

15 ENDPOINTS SHA-256 PRODUCT CODES ANALYTICS

What follows: Each submodule above will be expanded into a full section with database schemas, complete API endpoint documentation, frontend form fields, validation rules, code snippets, and the reasoning behind key design decisions.

6.1 MACHINE MANAGEMENT

Before you can design a cable, you need to tell the system what machines the factory has. Machine Management is the registry of every physical machine on the production floor — its brand, model, and most importantly, its capability ranges. These ranges (speed min/max, diameter min/max, etc.) are used throughout the system to generate dropdown options and validate that a cable design is physically producible.

Why one table per machine type? Each machine type has fundamentally different configurable parameters. A Kabatel Çekme has tav (anneal current) and output diameter. A Buncher has hatve (lay length) and input count. An Aktarma has no parameters at all. Rather than a single table with dozens of nullable columns, each type gets its own table with exactly the columns it needs. The database CHECK constraints can then enforce physical sanity per machine type.

6.1.1 The Seven Machine Types

The factory’s production line consists of 7 machine types, each performing a specific step in the cable manufacturing process:

#Machine TypeTurkish NameWhat It DoesConfigurable Parameters
1Kabatel ÇekmeKabatel ÇekmeDraws thick copper rod (8mm filmaşin) into thinner wireSpeed (m/s), TAV (A), Output Diameter (mm)
2KalaylamaKalaylamaCoats drawn wire with tin for conductivity and corrosion resistanceSpeed (m/s), Tin Thickness (μm)
3İncetel Çekmeİncetel ÇekmeDraws wire to even finer diameters, optionally from multiple inputsSpeed (m/s), Input Count, Output Diameter (mm), TAV (A)
4BuncherBuncherTwists multiple wires into a bundle (strand)Speed (m/s), Hatve/Lay Length, Input Count, Twist Direction (S/Z)
5ExtruderEkstrüderApplies insulation and/or sheath layers (plastic coating)Speed (m/s), Insulation Thickness (mm), Sheath Thickness (mm)
6E-beamE-beamCross-links insulation via electron beam radiationSpeed (m/s), Radiation Level (kGy)
7AktarmaAktarmaTransfers/rewinds cable between spools (no transformation)None (brand/model only)

6.1.2 Database Schema

7 tables, one per machine type. All share a common structure (id, brand, model, is_active, created_by, timestamps) plus type-specific parameter columns stored as min/max/increment triplets.

Common Columns (all 7 tables)

ColumnTypeNullableDefaultNotes
idIntegerNoAutoPrimary key, indexed
brandString(100)NoMachine manufacturer
modelString(100)YesNULLMachine model designation
is_activeBooleanNoTrueIndexed; soft-delete flag
created_byIntegerYesNULLFK → users.id
created_atDateTimeNoutcnowCreation timestamp
updated_atDateTimeNoutcnowAuto-updates on change

Kabatel Çekme — kabatel_cekme_machines

ColumnTypeUnitCHECK Constraint
speed_minFloatm/s≥ 0
speed_maxFloatm/s> speed_min
speed_incrementFloatm/s> 0
tav_minFloatAmpere≥ 0
tav_maxFloatAmpere> tav_min
tav_incrementFloatAmpere> 0
output_minFloatmm> 0
output_maxFloatmm> output_min
output_incrementFloatmm> 0
input_typeString(50)Default: '8mm_filmaşin'
input_codeString(10)Default: 'A'

Kalaylama — kalaylama_machines

ColumnTypeUnitCHECK Constraint
speed_minFloatm/s≥ 0
speed_maxFloatm/s> speed_min
speed_incrementFloatm/s> 0
thickness_minFloatμm> 0
thickness_maxFloatμm> thickness_min
thickness_incrementFloatμm> 0
input_codeString(10)Default: 'X'

İncetel Çekme — incetel_cekme_machines

ColumnTypeUnitCHECK Constraint
speed_min/max/incrementFloatm/sSame pattern as above
input_number_minInteger≥ 1
input_number_maxInteger≥ input_number_min
output_min/max/incrementFloatmmSame pattern as above
tav_min/max/incrementFloatAmpereSame pattern as above

Buncher — buncher_machines

ColumnTypeUnitCHECK Constraint
speed_min/max/incrementFloatm/sSame pattern
hatve_minFloatmm> 0
hatve_maxFloatmm> hatve_min
hatve_incrementFloatmm> 0
input_number_minInteger≥ 0
input_number_maxInteger≥ input_number_min
accepted_input_codesTextDefault: 'Z,T,U'

Extruder — extruder_machines

ColumnTypeUnitCHECK Constraint
speed_min/max/incrementFloatm/sSame pattern
insulation_thickness_minFloatmm> 0
insulation_thickness_maxFloatmm> insulation_thickness_min
insulation_thickness_incrementFloatmm> 0
sheath_thickness_minFloatmm> 0
sheath_thickness_maxFloatmm> sheath_thickness_min
sheath_thickness_incrementFloatmm> 0
accepted_input_codesTextDefault: 'T,Z'

E-beam — ebeam_machines

ColumnTypeUnitCHECK Constraint
speed_min/max/incrementFloatm/sSame pattern
radiation_level_minFloatkGy> 0
radiation_level_maxFloatkGy> radiation_level_min
radiation_level_incrementFloatkGy> 0

Aktarma — aktarma_machines

No configurable parameters. Only the common columns (brand, model, is_active, timestamps). No CHECK constraints beyond the common ones.

6.1.3 Options Generation — The Core Mechanism

This is the mechanism that makes the entire Machine Management → Playground pipeline work. When the Playground needs to show dropdown options for a machine parameter, it calls the /options endpoint, which steps through the min/max/increment range and returns every valid value.

def generate_dropdown_options(min_val, max_val, increment):
    options = []
    current = min_val
    while current <= max_val:
        options.append(round(current, 4))  # Avoid floating point drift
        current += increment
    return options

# Example: machine with speed_min=5, speed_max=25, speed_increment=5
# → [5.0, 10.0, 15.0, 20.0, 25.0]

Special cases:

Multi-machine intersection: When the Playground selects multiple machines of the same type, the system calculates the intersection of their capability ranges. If Machine A supports speeds [5, 10, 15, 20] and Machine B supports [10, 15, 20, 25], the dropdown shows [10, 15, 20]. This lives in the Playground’s db_integration.py, not here — but it consumes the options generated by this module.

6.1.4 API Endpoints

38 total endpoints. Each machine type gets 5–6 endpoints following a consistent pattern (except Aktarma which has no /options).

Pattern per machine type (replace {type} with e.g. kabatel-cekme)

MethodPathPermissionWhat It Does
GET/teknik/machines/{type}AuthenticatedList all machines. ?active_only=true (default). Ordered by brand, model.
GET/teknik/machines/{type}/{id}AuthenticatedSingle machine detail. Returns 404 if not found.
GET/teknik/machines/{type}/{id}/optionsAuthenticatedGenerate dropdown values from min/max/increment ranges.
POST/teknik/machines/{type}super_admin, production_managerCreate machine. Sets created_by. Broadcasts real-time update.
PUT/teknik/machines/{type}/{id}super_admin, production_managerPartial update. Only provided fields are changed.
DELETE/teknik/machines/{type}/{id}super_admin onlyHard delete. Returns 204 No Content.

Common endpoints

MethodPathWhat It Does
GET/teknik/machines/typesReturns all 7 type names as string array
GET/teknik/machines/allReturns all machines of all types in one response, keyed by type name

Options response shapes per type

Machine TypeOptions Fields
Kabatel Çekmespeeds, tavs, output_diameters
Kalaylamaspeeds, thicknesses
İncetel Çekmespeeds, input_numbers (int), output_diameters, tavs
Buncherspeeds, hatves, input_numbers (int), twist_directions (hardcoded S/Z)
Extruderspeeds, insulation_thicknesses, sheath_thicknesses
E-beamspeeds, radiation_levels
Aktarma— (no options endpoint)

6.1.5 Permission Model

Uses check_permission_smart() which supports both the legacy user_type system and the granular permission system:

ActionLegacy RolesGranular Permission
View / List / OptionsAny authenticated userAny authenticated user
Create / Updatesuper_admin, production_managerteknik.machines.create / teknik.machines.edit
Deletesuper_admin onlyteknik.machines.delete

6.1.6 Frontend — The Machines Page

Single file: pages/Teknik/Machines/index.tsx (726 lines). Route: /teknik/machines, protected by canTeknik access flag.

Page Structure

A PageContainer wrapping a Card with 7 Tabs — one per machine type. Switching tabs fetches the machine list for that type and resets the search text. Default tab: Kabatel Çekme.

Table Columns

Every tab shows a ProTable with these base columns plus type-specific ones:

ColumnWidthNotes
ID60pxFixed left
Marka (Brand)autoEllipsis enabled
ModelautoShows “-” if empty
Type-specific rangesautoFormatted as “min–max unit”
Durum (Status)80pxGreen “Aktif” / Red “Pasif” tag
İşlemler (Actions)100pxFixed right; edit + delete icons

Type-specific columns:

Search & Pagination

Search is client-side: a text input filters the loaded list by ID, brand, model, or status (“aktif”/“pasif”). No server-side search needed because machine counts are small (typically <50 per type).

Pagination defaults to 10 rows, with options [10, 20, 50, 100]. Total shown as “X-Y / Z kayıt”.

CRUD Flow

Create:

  1. Click “Yeni Makine Ekle” button in the toolbar
  2. Modal opens with title “Yeni Makine Ekle” (600px, blurred backdrop)
  3. Form shows fields dynamically based on active tab (machine type)
  4. On submit: POST /api/teknik/machines/{type} with form values
  5. System fields (id, created_at, updated_at, created_by, input_type, input_code, accepted_input_codes) are automatically excluded
  6. On success: toast “Makine başarıyla eklendi!”, close modal, refresh list

Edit:

  1. Click edit icon in the Actions column
  2. Modal opens with title “Makine Düzenle”, pre-filled with current values
  3. On submit: PUT /api/teknik/machines/{type}/{id} with changed fields only
  4. On success: toast “Makine başarıyla güncellendi!”, close modal, refresh list

Delete:

  1. Click delete icon in the Actions column
  2. Popconfirm asks: “Bu makineyi devre dışı bırakmak istediğinize emin misiniz?”
  3. Delete button is disabled if machine is already inactive
  4. On confirm: DELETE /api/teknik/machines/{type}/{id}
  5. On success: toast “Makine devre dışı bırakıldı!”, refresh list

Form Fields Per Machine Type

The form renders dynamically via renderFormFields() based on the active tab. Common fields (Marka, Model) appear for all types. Type-specific fields use InputNumber with appropriate min, step, and Turkish labels:

Machine TypeForm Fields (beyond Marka/Model)
Kabatel ÇekmeHız: min (0), max (0.1), increment (0.1) • Tav: min (0), max (1), increment (1) • Çıkış Çapı: min/max/increment (all step 0.01)
KalaylamaHız: min/max/increment • Kalay Kalınlığı: min/max/increment (step 0.1)
İncetel ÇekmeGirdi Sayısı: min (1), max (1) • Hız: min/max/increment • Çıkış Çapı: min/max/increment (step 0.01) • Tav: min/max/increment
BuncherGirdi Sayısı: min (0), max (1) • Hız: min/max/increment • Hatve: min/max/increment (step 0.1)
ExtruderHız: min/max/increment • İzolasyon Kalınlığı: min/max/increment (step 0.01) • Kılıf Kalınlığı: min/max/increment (step 0.01)
E-beamHız: min/max/increment • Radyasyon Seviyesi: min/max, increment (step 1)
AktarmaNone (Marka/Model only)

6.1.7 Service Layer (Frontend)

API calls are wrapped in services/teknik/index.ts with a URL transformation: underscores in the machine type name are replaced with hyphens for the URL path.

// kabatel_cekme → kabatel-cekme in URL
export async function getMachines(type: MachineType) {
  return request(`/api/teknik/machines/${type.replace('_', '-')}`);
}

export async function createMachine(type: MachineType, data: any) {
  return request(`/api/teknik/machines/${type.replace('_', '-')}`, {
    method: 'POST', data
  });
}

// Same pattern for updateMachine (PUT), deleteMachine (DELETE)
// getMachineDropdown calls /{id}/dropdown for Playground use

6.1.8 How It Connects to Other Submodules

→ Cable Playground (6.5)

The primary consumer. When you add a machine to the canvas and configure it, the Playground calls the /options endpoint to populate dropdowns. When multiple machines are selected, it reads all their ranges and calculates the intersection — only showing parameter values all selected machines can physically produce.

→ Cable Database (6.6)

Indirect. Machine IDs are stored in each DesignStep’s machine_ids field. The Cable Database stores the finalized design including which specific machines were used, so Production knows which physical machine to assign each step to.

→ Üretim (Production Module)

When a work card is generated, the production system reads which machines a cable design requires. Machine IDs stored in the design map directly to the registry maintained here.

Design principle: Machine Management is a pure data provider. It knows nothing about designs, orders, or production. It only answers the question “what can this machine do?” — everything else is the consumer’s responsibility. This keeps the module simple (~726 lines frontend, ~38 endpoints) and makes it the most stable part of the Teknik subsystem.

6.2 STANDARDS MANAGEMENT

Every cable sold must pass a set of quality tests defined by international standards bodies (IEC, CENELEC) or the customer. Standards Management is where those tests are defined — what to measure, how many samples, with which parameters, and what the reference standard number is. These definitions are then embedded into cable designs so that the Lab module knows exactly what to test and when during production.

Three layers of quality: IEC-EN covers European harmonized standards (EN 50618, IEC 60228). UL covers American standards (UL 4703, UL 854). SLN covers Solen’s own internal tests — company-specific checks that go beyond what the standards require. When a cable design is created in the Playground, only tests matching the design’s standard category are shown.

6.2.1 Data Model

Three tables work together: standards define what to test, parameters define what to measure within each test, and results store the actual measurements from production.

test_standards

ColumnTypeNullableConstraints / DefaultNotes
idIntegerNoPK, indexed
standard_categoryString(50)NoCHECK: IN (‘IEC-EN’, ‘UL’, ‘SLN’)Which standards body
test_nameString(200)NoTurkish test name
test_name_enString(200)YesEnglish test name
standard_numberString(100)Yese.g. “EN 50618”, “IEC 60228”
test_typeString(100)YesFree-form: Mekanik, Elektriksel, Görsel, Boyutsal
unitString(50)Yese.g. “ohm/km”, “kV”, “N/mm²”
number_of_valuesIntegerNoDefault: 1, CHECK: ≥ 1How many values per measurement
test_samplesIntegerNoDefault: 1, CHECK: ≥ 1How many samples to test
test_methodTextYesFree-text test procedure description
is_activeBooleanNoDefault: True, indexedSoft-delete flag
created_byIntegerYesFK → users.id
created_atDateTimeNoutcnow
updated_atDateTimeNoutcnow, auto-updates

Unique constraint: (standard_category, test_name, standard_number) — prevents duplicate test definitions within the same standards body.

test_parameters

ColumnTypeNullableConstraints / DefaultNotes
idIntegerNoPK, indexed
test_standard_idIntegerNoFK → test_standards.id, ON DELETE CASCADE
parameter_nameString(100)Noe.g. “Çekme Dayanımı”, “Uzama”, “Direnç”
parameter_unitString(50)Yese.g. “N/mm²”, “%”, “ohm/km”
parameter_orderIntegerNoDefault: 1Display order in forms
is_requiredBooleanNoDefault: TrueMust be filled during testing
created_atDateTimeNoutcnow

Unique constraint: (test_standard_id, parameter_name) — no duplicate parameter names within a single test.

test_results

ColumnTypeNullableConstraints / DefaultNotes
idIntegerNoPK, indexed
test_standard_idIntegerNoFK → test_standards.idWhich test was performed
design_step_idIntegerYesFK → design_steps.idLinks result to specific production step
production_session_idIntegerYesLinks to production session
cable_batch_codeString(50)YesIndexedBatch identifier for traceability
test_dateDateTimeNoWhen the test was performed
tested_byIntegerNoFK → users.idWho performed the test
measurementsTextNoJSON string of measurement data
pass_failString(10)YesCHECK: IN (‘PASS’, ‘FAIL’, ‘PENDING’) OR NULLTest outcome
notesTextYesAppended with timestamps by status updates
created_atDateTimeNoutcnow

Measurement storage: The measurements column stores a JSON array. Each entry is a MeasurementData object with parameter (name), values (float array), optional unit, and optional per-parameter result. The model has helper methods: get_measurements() parses the JSON, set_measurements() serializes it, and evaluate_result() returns PASS/FAIL/PENDING based on whether all required parameters have values.

6.2.2 Relationships

TestStandard
N × TestParameter
cascade delete
TestStandard
N × TestResult
no cascade

Delete behavior is smart: if a standard has test results, it is soft deleted (is_active = false) to preserve result traceability. If it has no results, it is hard deleted. Parameters always cascade — deleting a standard removes all its parameters.

6.2.3 API Endpoints

12 endpoints organized into three groups: standards CRUD, parameter management, and test results.

Test Standards

MethodPathPermissionWhat It Does
POST/teknik/testssuper_admin, lab_user, production_managerCreate standard + parameters in one transaction. Checks for duplicate (category + name + number). Flushes DB to get ID before adding parameters.
GET/teknik/testsAuthenticatedList all. ?category=IEC-EN, ?active_only=true (default), ?search=tensile. Eager-loads parameters. Orders by category then name.
GET/teknik/tests/{id}AuthenticatedSingle standard detail.
GET/teknik/tests/{id}/fullAuthenticatedFull standard with sorted parameters + has_parameters flag. Used by Playground for dynamic form generation.
PUT/teknik/tests/{id}super_admin, lab_user, production_managerUpdate standard. If parameters provided: deletes all existing, creates new ones (full replacement).
DELETE/teknik/tests/{id}super_admin, lab_userSmart delete: soft if has results, hard if no results.

Test Parameters

MethodPathPermissionWhat It Does
POST/teknik/tests/{id}/parameterssuper_admin, lab_user, production_managerAdd single parameter to existing standard. Checks duplicate name.
DELETE/teknik/parameters/{id}super_admin, lab_userHard delete single parameter.

Test Results

MethodPathPermissionWhat It Does
POST/teknik/resultslab_user, super_adminCreate result with measurements JSON. Auto-sets tested_by. Calls evaluate_result() for initial pass/fail.
GET/teknik/resultsAuthenticatedList results. Filter by ?batch_code, ?test_standard_id, ?pass_fail. Limit: 1–200, default 50. Ordered by test_date DESC.
GET/teknik/results/{id}AuthenticatedSingle result with tester name and standard info.
PUT/teknik/results/{id}/statuslab_user, super_adminUpdate pass/fail status. Appends notes with timestamp and username for audit trail.

Reference Data

MethodPathReturns
GET/teknik/categories["IEC-EN", "UL", "SLN"]
GET/teknik/frequencies["üretim_başı", "üretim_sonu", "her_ikisi", "her_makara_sonu"]
GET/teknik/result-statuses["PASS", "FAIL", "PENDING"]

6.2.4 Test Frequencies — When Tests Run

When a test is assigned to a cable design step in the Playground, the user selects a frequency that tells the Lab when to execute the test during production:

FrequencyTurkishMeaning
üretim_başıÜretim BaşıTest at the start of the production run
üretim_sonuÜretim SonuTest at the end of the production run
her_ikisiHer İkisiTest at both start and end
her_makara_sonuHer Makara SonuTest at the end of every reel (most frequent)

6.2.5 How Standards Connect to Cable Designs

This is the critical integration point. When the Playground configures a machine step, tests are fetched and filtered by the design’s standard category:

# In db_integration.py — fetches tests matching the design's standard
def get_tests_by_standard(db, standard):
    # Maps frontend code to database category
    category_map = {'EN': 'IEC-EN', 'UL': 'UL', 'SLN': 'SLN'}
    category = category_map.get(standard, standard)

    standards = db.query(TestStandard).filter(
        TestStandard.standard_category == category,
        TestStandard.is_active == True
    ).all()
    return [{'id': s.id, 'test_name': s.test_name, ...} for s in standards]

When a design is finalized, the assigned tests are stored as a JSON array in cable_database.test_requirements:

# Storage format in cable_database.test_requirements
[
  {
    "step": 3,
    "machine_type": "extruder",
    "test_id": 12,
    "test_name": "Çekme Dayanımı",
    "standard_number": "EN 50618",
    "frequency": "her_ikisi"
  }
]

Denormalized by design: Test names and standard numbers are copied into the Cable Database JSON, not just referenced by ID. This means if a test standard is later renamed or deactivated, existing cable designs retain their original test requirements. The Lab reads from Cable Database at production time — it never needs to query the Standards table to know what to test.

6.2.6 Permission Model

ActionLegacy RolesGranular Permission
View / List / SearchAny authenticated userAny authenticated user
Create / Updatesuper_admin, lab_user, production_managerteknik.standards.create / teknik.standards.edit
Deletesuper_admin, lab_userteknik.standards.delete
Create / Update Resultslab_user, super_adminteknik.standards.create

Note: lab_user has wider access here than in Machine Management — this is intentional because lab personnel are the primary users of the standards system.

6.2.7 Frontend — Standards Page

Single file: pages/Teknik/Standards/index.tsx (553 lines). Route: /teknik/standards.

Page Structure

PageContainer with a ProTable and a modal for create/edit. No tabs — all standards shown in one table, category distinguished by color-coded tags.

Table Columns (9)

ColumnWidthNotes
ID60pxFixed left
Kategori100pxColor-coded tag: IEC-EN blue, UL green, SLN orange
Test AdıautoTurkish test name, ellipsis
Standart No150pxe.g. “EN 50618”
Test Tipi120pxShows “-” if empty
Numune Sayısı100pxCentered integer
Parametre100pxShows parameter count (e.g. “3”)
Durum80pxGreen “Aktif” / Red “Pasif”
İşlemler100pxFixed right; edit + delete icons

Create/Edit Modal (800px, blurred backdrop)

The modal contains 7 form fields plus a dynamic parameter list:

FieldTypeRequiredNotes
Standart KategorisiSelectYesOptions: IEC-EN, UL, SLN (Özel)
Test Adı (TR)InputYesPlaceholder: “Örn: Çekme Dayanımı”
Test Adı (EN)InputNoPlaceholder: “Örn: Tensile Strength”
Standart NumarasıInputYesPlaceholder: “Örn: EN 50618”
Test TipiSelectNoOptions: Mekanik, Elektriksel, Görsel, Boyutsal
Numune SayısıInputNumberNoMin: 1
Test MetoduTextAreaNo3 rows, procedure description

Parameter Management (inside modal)

Below a “Test Parametreleri” divider, each parameter is rendered as a small Card with two fields:

“Parametre Ekle” button (dashed, full-width) adds a new empty parameter card. Each card has a delete button in the header. Order is auto-assigned sequentially. On update, all existing parameters are replaced with the new set (delete all + create new).

CRUD Flow

Create: Click “Yeni Test Standardı” → Modal opens → Fill category, name, standard number → Optionally add parameters → Click “Ekle” → POST /api/teknik/standards/tests → Toast “Test standardı başarıyla eklendi!” → Modal closes, list refreshes.

Edit: Click edit icon → Modal opens pre-filled → Modify fields/parameters → Click “Güncelle” → PUT /api/teknik/standards/tests/{id} → Toast “Test standardı başarıyla güncellendi!” → Modal closes, list refreshes.

Delete: Click delete icon → Popconfirm “Bu standardı devre dışı bırakmak istediğinize emin misiniz?” → DELETE /api/teknik/standards/tests/{id} → Toast “Test standardı devre dışı bırakıldı!” → List refreshes. Delete button disabled for already-inactive standards.

Search & Pagination

Search is client-side (200px rounded input). Searches across ID, category, test name, standard number, test type, sample count, and status (aktif/pasif). Pagination defaults to 10 rows with [10, 20, 50, 100] options. Sorted by ID descending (newest first).

6.2.8 How It Connects to Other Submodules

→ Cable Playground (6.5)

Every machine form in the Playground includes an available_tests section populated via get_tests_by_standard(). Users assign tests to steps with a frequency. The Playground’s form integration reads from Standards but never writes to it.

→ Cable Database (6.6)

Finalized designs store test_requirements as denormalized JSON — test IDs, names, standard numbers, and frequencies copied at finalization time. This snapshot ensures immutability.

→ Lab Module

During production, the Lab reads test requirements from Cable Database and creates TestResult records linked to the standard. Lab users fill measurements and set pass/fail status with timestamped notes for audit trail.

Design principle: Standards are defined once, embedded into designs by value (not by reference), and tested during production. The three-table structure (standard → parameters → results) separates definition from execution. Standards Management never touches production data — it only answers “what should be tested?”, leaving “what was the result?” to the Lab module.

6.3 OPERATOR MANAGEMENT

Production operators are the people running the machines on the factory floor. They don’t need system logins — they are simply names in a registry that get assigned to production sessions when someone starts a manufacturing run. This is the simplest submodule in Teknik (284 lines of frontend, 4 endpoints), but its data appears in every production session, every work card, and every half-product record.

Two kinds of “operator” in the system: ProductionOperator (this submodule) is a simple name registry — no login, no password, no permissions. The separate Operator model in the User system extends user accounts for operator-type users who log into the system. When an operator starts a production session, they select their own name from the ProductionOperator registry. The work card they’re producing was planned earlier by a production manager via the planning module.

6.3.1 Database Schema

production_operators

ColumnTypeNullableConstraints / DefaultNotes
idIntegerNoPK, indexed
nameString(100)NoUNIQUEOperator’s full name
is_activeBooleanNoDefault: TrueActive status flag
created_atDateTimeNoutcnow
updated_atDateTimeNoutcnow, auto-updates

That’s the entire table. Five columns. No foreign keys, no relationships, no JSON blobs. The UNIQUE constraint on name is the only business rule — you can’t have two operators with the same name.

No relationships defined. The ProductionOperator model has zero SQLAlchemy relationships. Production sessions reference operators by storing the operator_name as a denormalized string — not a foreign key. This means deleting an operator doesn’t cascade to sessions, but it also means old session records always retain the correct operator name even if the operator is later removed.

6.3.2 API Endpoints

4 endpoints under /operators. Notably, there are no role checks beyond authentication — any logged-in user can manage operators. No Pydantic schemas either; the routes accept and return raw dictionaries.

MethodPathPermissionWhat It Does
GET/operators/listAuthenticatedList all operators. ?active_only=true (default). Ordered by name ascending. Returns array + total count.
POST/operators/createAuthenticatedCreate operator. Trims name, checks empty, checks duplicate. Sets is_active=true.
PUT/operators/{id}AuthenticatedUpdate operator name. Checks exists, checks empty, checks duplicate (excluding self).
DELETE/operators/{id}AuthenticatedHard delete. No cascade check. May fail if referenced by production sessions.

Validation Details

CheckWhenError Message (Turkish)
Name emptyCreate / Update“Operatör adı gerekli”
Name duplicateCreate“‘{name}’ adında operatör zaten mevcut”
Name duplicate (excl. self)Update“‘{name}’ adında başka operatör zaten mevcut”
Not foundUpdate / Delete“Operatör bulunamadı”

6.3.3 How Operators Are Used in Production

This is where the simple name registry becomes critical. When a production session starts, the operator is assigned and their name is stored directly in the session record:

# In production_routes.py — starting a production session
if request.operator_id:
    prod_operator = db.query(ProductionOperator).filter(
        ProductionOperator.id == request.operator_id
    ).first()
    if prod_operator:
        operator_name = prod_operator.name

# Stored in production_sessions table:
# operator_id  → current_user.id (FK to users, for DB integrity)
# operator_name → prod_operator.name (denormalized, for history)

The Dual Storage Pattern

Production sessions store operator information in two ways:

ColumnPoints ToPurpose
operator_idFK → users.idDatabase integrity (the user who started the session)
operator_nameString (denormalized)The production operator running the machine (from this registry)

This separation exists because the system tracks both who is logged in (the user account, stored as operator_id FK) and which production operator is physically running the machine (the name from this registry, stored as operator_name). The operator selects their own name from a dropdown when starting a production session for a work card that was pre-planned by the production manager.

Operator in the Production Lifecycle

Registry
Names defined here
Session Start
Select operator
Production
Name stored in session
History
Preserved forever

6.3.4 Frontend — Operator Page

Single file: pages/Teknik/OperatorYonetimi/index.tsx (284 lines). Route: /teknik/operator-yonetimi. The smallest page in the entire Teknik module.

Table Columns (3)

ColumnWidthNotes
ID80pxFixed left
Operatör AdıautoEllipsis enabled
İşlemler100pxFixed right; edit + delete icons

No status column, no timestamps. Just the name. The is_active and created_at/updated_at fields exist in the data interface but are not displayed.

Create/Edit Modal (400px, blurred backdrop)

One field:

FieldTypeRequiredNotes
Operatör AdıInput (large)YesPlaceholder: “Operatör adını girin”

CRUD Flow

Create: Click “Yeni Operatör” → Modal (400px) → Enter name → Click “Oluştur” → POST /api/operators/create → Toast “Operatör oluşturuldu” → Modal closes, list refreshes.

Edit: Click edit icon → Modal pre-filled → Change name → Click “Güncelle” → PUT /api/operators/{id} → Toast “Operatör güncellendi” → Modal closes, list refreshes.

Delete: Click delete icon → Popconfirm “Operatörü silmek istediğinize emin misiniz?” → DELETE /api/operators/{id} → Toast “Operatör silindi” → List refreshes.

Search & Pagination

Search is client-side (200px input). Filters by name and ID (case-insensitive). Pagination defaults to 20 rows (higher than other pages, since the operator list is short), with [10, 20, 50, 100] options.

How Operators Appear in Production Pages

Production pages (KabatelÇekme, Kalaylama, etc.) show operator selection in two states:

6.3.5 How It Connects to Other Submodules

→ Üretim (Production Module)

Primary consumer. Every production session requires an operator. The name is stored denormalized in the session record. Operators can be changed mid-session for shift handoffs. Production history displays operator per session.

→ Stok (Stock Module)

Half-product records trace back to the production session that created them. Stock pages resolve session.operator_name to show which operator produced each item — full production traceability.

Design principle: Radical simplicity. One table, one field that matters (name), four endpoints, no role checks beyond authentication. The complexity lives in how production consumes this data — the dual storage pattern (FK for integrity, name for history) is the clever part. An operator’s name is entered once into the registry, and from then on they simply pick it from a dropdown each time they start a production session — that name then follows every meter of cable they produce.

6.4 Markalama (Cable Marking)

Every meter of cable that leaves the factory has text physically printed on its sheath — company name, standard, voltage rating, cross-section, production year. Markalama is the submodule that manages these marking templates: ordered arrays of words/segments that the extruder machine prints during cable production.

What a marking template is: Not a single string, but an ordered JSON array of words. Each word is printed sequentially on the cable during extrusion, repeating along the cable’s entire length. Words can include dynamic variables ({CABLE_SIZE}, {ORDER_NO}, {YEAR}, {METER}) that are resolved at production time. Example: ["SOLEN BEAM", "TUV RHEINLAND", "H07V-K", "{CABLE_SIZE}", "{YEAR}"] → prints SOLEN BEAM · TUV RHEINLAND · H07V-K · 4mm² · 2025 repeating along the cable.

6.4.1 Database Schema

One table. Minimal design.

ColumnTypeConstraintsPurpose
idIntegerPK, auto-increment, indexedUnique identifier
nameString(200)UNIQUE, NOT NULL, indexedTemplate name (e.g. “SOLEN BEAM Standard”)
wordsJSONNOT NULLOrdered array of strings — the words printed on the cable
is_activeBooleanNOT NULL, default trueSoft delete flag. Inactive markings hidden from order dropdowns.
created_atDateTime(tz)server default now()Creation timestamp
updated_atDateTime(tz)on update now()Last modification timestamp

JSON storage for words: The words column stores a JSON array (e.g. ["SOLEN BEAM", "TUV RHEINLAND", "H07V-K"]). The backend handles both native JSON and string-encoded JSON — the list endpoint explicitly parses: json.loads(m.words) if isinstance(m.words, str) else m.words. This dual handling ensures robustness regardless of how the database driver serializes the column.

Key Constraints

6.4.2 API Endpoints

Six endpoints under /api/teknik/markings:

MethodPathPermissionWhat It Does
POST/markings/createsuper_admin + teknik.markalama.create_markingCreate template. Checks duplicate name. Stores name + words array.
GET/markings/listAuthenticatedList all. ?active_only=true (default), ?search=solen (name ilike). Ordered by name. Parses JSON words.
GET/markings/{id}AuthenticatedSingle marking by ID.
PUT/markings/{id}super_admin + teknik.markalama.update_markingPartial update. If name changes, checks for conflicts. Only provided fields are modified.
DELETE/markings/{id}/hard-deletesuper_admin + teknik.markalama.delete_markingPermanent delete. No soft delete on this endpoint.
PUT/markings/{id}/toggle-statusAuthenticatedFlip is_active between true/false. No permission check beyond auth.

Validation Details

CheckWhereDetails
Name requiredSchema (min_length=1)Pydantic rejects empty strings
Name max lengthSchema + DBmax_length=200 in Pydantic, String(200) in SQLAlchemy
Words non-emptySchema validatorCustom @validator('words') ensures len(v) > 0
Duplicate nameRoute handlerQueries DB before create. On update, excludes self (Marking.id != marking_id)
Exists checkRoute handler404 if marking not found on get/update/delete

Delete Behavior

The delete endpoint is hard delete (db.delete(marking)). Unlike Standards Management, there is no smart delete logic. If a marking is referenced by existing orders, those orders retain the marking_id integer but the marking record is gone. The safer workflow is to toggle status to inactive using the /toggle-status endpoint, which hides the marking from new orders while keeping the record intact for historical lookups.

6.4.3 Pydantic Schemas

SchemaFieldsUsed By
MarkingCreateRequestname: str, words: List[str] (min 1 item)POST create
MarkingUpdateRequestname?: str, words?: List[str], is_active?: boolPUT update (all optional for partial)
MarkingResponseid, name, words, is_active, created_at, updated_atAll responses
MarkingListResponsesuccess: bool, data: List[MarkingResponse], message: strDefined but not used (list returns raw array)

Unused wrapper: MarkingListResponse is defined in schemas but the /list endpoint returns a raw array, not the wrapper. The endpoint manually constructs dictionaries with parsed JSON words instead of using the Pydantic response_model. This is a pragmatic choice to handle the JSON string/native dual format.

6.4.4 Dynamic Variables

Marking words support four runtime variables that get resolved during production:

VariableResolves ToExample
{CABLE_SIZE}Cable cross-section from order4mm²
{ORDER_NO}Order numberSLN-2025-0042
{YEAR}Production year2025
{METER}Running meter mark on cable150

Variable resolution happens at the production/extrusion layer, not in this submodule. Markalama just stores the templates with placeholder syntax. The frontend displays these as helper text in the form: “Değişkenler: {CABLE_SIZE}, {ORDER_NO}, {YEAR}, {METER}”.

6.4.5 Permission Model

ActionRole CheckPermission Key
View / List / SearchAny authenticated userAny authenticated user
Createsuper_adminteknik.markalama.create_marking
Updatesuper_adminteknik.markalama.update_marking
Deletesuper_adminteknik.markalama.delete_marking
Toggle StatusAny authenticated userNo additional check

Unlike Machines (which allow production_manager) or Standards (which allow lab_user), Markalama write operations are restricted to super_admin only. The check_permission_smart function validates both the role and the granular permission key. The toggle-status endpoint is an exception — any authenticated user can activate/deactivate a marking.

Permission Manifest (Frontend)

The frontend permission system defines 5 buttons for the Markalama page:

6.4.6 Frontend — Page Structure

Single file: src/pages/Teknik/Markalama/index.tsx (374 lines). Route: /teknik/markalama.

PageContainer

Ant Design Pro wrapper with title “Markalama”.

ProTable

Main data table. Fetches from /api/teknik/markings/list with active_only=false (shows all, including inactive). Client-side search and pagination.

Modal (700px)

Create/edit form. Contains name input + dynamic word list (Form.List). Blur-on-backdrop effect.

Table Columns (4)

#ColumnWidthFeatures
1İsim (Name)250pxFixed left. Sortable (localeCompare). Primary identifier.
2Kelime Sayısı (Word Count)120pxComputed: parses words JSON/array, returns .length. Not the words themselves.
3Durum (Status)100pxGreen <Tag> for Aktif, red for Pasif.
4İşlemler (Actions)100pxFixed right. Edit button + Delete with Popconfirm (“Are you sure?”).

Create/Edit Modal

The modal has two form sections:

1. Name Field

2. Words (Dynamic List)

CRUD Flow

Click “Yeni Markalama” Modal opens (1 empty word slot) Enter name + add words POST /markings/create Table refreshes (key increment)
Click edit icon Modal opens (pre-filled) Modify name/words PUT /markings/{id} Table refreshes
Click delete icon Popconfirm dialog DELETE /markings/{id}/hard-delete Table refreshes

Search & Pagination

Search is client-side (200px rounded input). Filters on name, status text (aktif/pasif), and word count number. Pagination defaults to 10 rows, options [10, 20, 50, 100]. Shows “X-Y / Z kayıt” total.

6.4.7 How Markings Flow Through the System

Markalama templates are reference data. They are created once in the Teknik module and then consumed at two critical points in the order-to-production pipeline:

Step 1: Order Creation (Sipariş Module)

Order creation page loads GET /markings/list?active_only=true Populate marking dropdown per cable

In the order creation form, each cable entry has a “Markalama” dropdown (searchable <Select>). It shows only active markings. The user picks one, and the marking_id is stored in order_cables.marking_id (integer FK). Marking selection is required for a cable to be considered “complete” in the order form.

// Order form cable completion check (SiparisOlustur/index.tsx)
const isComplete = hasDesign && hasMeters && hasMakara
  && hasMarking && hasPrice && hasCurrency && materialsComplete;

Step 2: Work Card Generation & Production Planning

When an order is confirmed and work cards are generated:

Order confirmed Work card generator reads cable data Resolves marking_id → marking_name Stores both in extruder material_details

The work_card_generator.py service resolves each cable’s marking_id to the actual marking name by querying the Marking table. Both marking_id and marking_name are embedded in the extruder work card’s material_details JSON:

# work_card_generator.py — extruder material_details
{
    'marking_id': cable_data.get('marking_id'),    # Integer FK
    'marking_name': cable_data.get('marking_name'), # Resolved text
    'tests': ex_tests,
    'breakdown': [],
    ...
}

Step 3: Production Planning Display

The Production Planning page reads the extruder work card’s material_details and displays the marking name in the card UI:

// Production/Planning/index.tsx
{materialDetails.marking_name && (
  <div>
    <div style={{ fontSize: 10, fontWeight: 600 }}>Markalama</div>
    <div style={{ fontSize: 11 }}>{materialDetails.marking_name}</div>
  </div>
)}

Step 4: Order Detail View

When viewing an existing order, the detail page shows the marking. The order_routes.py endpoint resolves marking_id to the name at query time:

# order_routes.py — marking resolution
marking_name = None
if cable.marking_id:
    marking = db.query(Marking).filter(Marking.id == cable.marking_id).first()
    marking_name = marking.name if marking else None

This pattern appears twice in order_routes.py: once for the single order detail endpoint, and once for the work card generation data extraction.

6.4.8 Data Storage Pattern — ID vs Name

Dual storage in consumption: Like the Operator dual storage pattern (6.3), markings use a hybrid approach — but split across different storage locations. The order_cables table stores only marking_id (integer). The work card material_details JSON stores both marking_id and marking_name (denormalized). This means order detail views must query the Marking table at runtime, but production planning can display the name directly from the JSON without an extra join.

6.4.9 Connections to Other Submodules

→ Sipariş (Order Module)

Primary consumer. Every cable in an order has a marking_id FK pointing to the markings table. The order creation page fetches active markings as a searchable dropdown. Marking is required for cable completion.

→ Üretim Planlama (Production Planning)

The work card generator resolves marking names and embeds them in extruder work card material_details. Production planning displays the marking name on extruder cards so operators know what text to verify on the cable.

→ Sipariş Detay (Order Detail View)

Order detail pages resolve marking_id to marking_name at query time. Displayed as a ValueDisplay component showing the template name.

Design principle: Template-based marking. Rather than storing free-text marking instructions per order, the system maintains a registry of reusable templates. This ensures consistency — every order for the same cable type uses the exact same marking text. The ordered word array structure maps directly to how the extruder printing head works: it cycles through the words sequentially, printing each segment with spacing between them along the cable’s length. Dynamic variables ({CABLE_SIZE}, {YEAR}, etc.) add order-specific context without creating new templates.

6.5 & 6.6 Kablo Tasarım (Cable Playground) & Kablo Veritabanı (Cable Database)

These two submodules are documented together because they are inseparable: Playground is where cables are designed step-by-step using real factory machines, and Cable Database is the permanent repository where finalized designs are stored. Every other module in the system — Orders, Production Planning, Work Cards, Material Calculations, Stock — ultimately depends on the records that Playground creates and saves into Cable Database.

The convergence point: This is where every other Teknik submodule merges. Machine Management provides the machines and their capability ranges. Standards Management provides the tests to assign at each step. Operator Management provides the operators who will execute the design. Markalama provides the text printed during extrusion. Playground consumes all of this data to create a complete production blueprint, which gets saved to Cable Database as the single source of truth for the entire manufacturing pipeline.

6.5.1 Core Concept — How Cable Design Works

Cable manufacturing follows a strict sequential pipeline. Raw copper (8mm filmaşin) enters the first machine and is progressively transformed through 6 machine types until a finished cable emerges. The Playground simulates this entire process digitally.

The Six Machine Types (in order)

#MachineInputOutputKey Parameters
1Kabatel Çekme8mm filmaşin (raw copper)Drawn wire (e.g. 1.8mm)output_diameter, speed, tav, adet
2KalaylamaDrawn wire from KCTinned wire (e.g. 21 pieces)tin_thickness, speed, adet (critical!)
3İncetel ÇekmeTinned wire from KLFine wire bundles (e.g. 10×0.30mm)input_number, output_diameter, output_number, tav
4BuncherFine wires from IC / other BN / EXBunched/twisted wiredynamic inputs (+ekle), hatve, twist_direction (S/Z)
5ExtruderBunched wire from BN / other EXInsulated/sheathed cableinsulation_thickness, sheath_thickness, catalyst, dye
6E-beamExtruded cable (no catalyst!)Cross-linked cableradiation_level, speed (set at production time)

Machine Flow Constraints

Not every machine can follow every other machine. The system enforces a directed graph:

Kabatel Çekme Kalaylama İncetel Çekme Buncher Extruder E-beam

Critical loop capabilities:

# Machine flow constraints (playground_session.py)
MACHINE_FLOW = {
    'kabatel_cekme': ['kalaylama'],
    'kalaylama':     ['incetel_cekme', 'buncher'],
    'incetel_cekme': ['buncher', 'extruder'],
    'buncher':       ['extruder', 'buncher'],    # Self-loop!
    'extruder':      ['ebeam', 'extruder'],      # Self-loop!
    'ebeam':         []                          # Terminal
}

6.5.2 Backend Architecture — The Engine

The Playground backend is built from 8 Python files totaling ~4,700 lines:

FileLinesPurpose
design_routes.py1,155API endpoints — session, steps, config, undo/redo, autosave, finalize
playground_session.py986Session manager — step lifecycle, undo/redo stacks, checkpoint/restore
progression_manager_v2.py995Quantity tracking — consume inputs, produce outputs, per-machine processing
db_integration.py446Real machine data — reads machine tables, capability intersection
form_integration.py339Form population — builds dropdown data per machine type
validation_engine.py465Configuration validation — checks ranges against machine capabilities
code_generator.py291Deterministic product codes — SHA256 hash + human-readable codes
playground_configs.py446Pydantic schemas — typed config for each machine type

Session Management (In-Memory)

Sessions are stored in a Python dictionary (_active_sessions: Dict[str, PlaygroundSession]). Each session contains:

The Progression Panel — Heart of the Design

The ProgressionManager maintains a list of ProgressionItem objects. Each item represents a physical product (wire, bunched wire, cable) at some stage of manufacturing:

# ProgressionItem fields
{
    'id': 'uuid',                    # Unique identifier
    'code': 'KC_18',                 # Deterministic product code
    'quantity': 21,                  # Current available amount
    'original_quantity': 21,         # Amount when first produced
    'structure': '1.8mm',            # Structure formula
    'specification': '1.8mm Tel',    # Human-readable name
    'status': 'active' | 'inactive', # Inactive = fully consumed
    'produced_by_step': 1,           # Which step created this
    'consumed_by_steps': [2],        # Steps that consumed from this
    'machine_type': 'kabatel_cekme', # Source machine
    'properties': { ... }            # Machine-specific data
}

Key rules:

Quantity Tracking Example — 6mm² Cable

8mm Filmaşin (qty: 1) → KC 1.8mm Tel (qty: 1) → KL (adet=21) 1.8mm Kalayı (qty: 21)
↓ IC (10 consumed) 10×0.30 (qty: 4)     ↓ IC (11 consumed) 11×0.30 (qty: 3)
↓ Buncher (4×10 + 3×11 = 73 wires) BN_73X030 (qty: 1) → EX EX_4X10X03_3X11X03+INS+SHT (qty: 1)

The critical adet parameter: At the Kalaylama step, adet=21 is what makes the entire 6mm² cable work. Kalaylama consumes 1 input but produces 21 pieces, which are then split between two parallel İncetel Çekme processes (10+11=21). This quantity tracking is the core innovation of the progression system.

Atomic Transactions with Checkpoint/Restore

Every configuration attempt is wrapped in an atomic transaction:

Create checkpoint Apply config Simulate step Success? Keep. Fail? Restore checkpoint.

The StateSnapshot captures the complete session state (steps + progression items + consumption log + step counter). On failure, the session is restored to exactly its previous state.

6.5.3 API Endpoints — 30+ Endpoints

Session Management

MethodPathWhat It Does
POST/playground/startStart session with standard + cross_section. Returns session_id + initial state.
GET/playground/{id}/stateGet full session state (steps + progression + summary).

Step Management

MethodPathWhat It Does
POST/playground/{id}/steps/addAdd machine step (sequential or parallel). Validates flow constraints.
DELETE/playground/{id}/steps/{step_id}Remove step with full rollback of consumed items. Reports affected dependent steps.

Form Data (per machine type)

MethodPathWhat It Does
GET/playground/{id}/form-data/kabatel-cekmeMachines, fixed input (8mm), tests for standard
GET/playground/{id}/form-data/kalaylamaMachines, inputs from progression (KC outputs), tests
GET/playground/{id}/form-data/incetel-cekmeMachines, tinned inputs with max_quantity, machine input limits
GET/playground/{id}/form-data/buncherMachines, Z/T/U-coded inputs with quantities, twist directions
GET/playground/{id}/form-data/extruderMachines, T/U-coded inputs, layer options (ins/sheath + catalyst/dye)
GET/playground/{id}/form-data/ebeamMachines, extruder outputs without catalyst only

Machine Configuration (per type)

MethodPathWhat It Does
POST/playground/{id}/configure/kabatel-cekme/{step}Configure KC: output_diameter, speed, tav, adet
POST/playground/{id}/configure/kalaylama/{step}Configure KL: input selection, tin_thickness, speed, adet
POST/playground/{id}/configure/incetel-cekme/{step}Configure IC: input, input_number, output_diameter, output_number
POST/playground/{id}/configure/buncher/{step}Configure BN: dynamic inputs, hatve, twist_direction
POST/playground/{id}/configure/extruder/{step}Configure EX: inputs (1+ for twin), ins/sheath layers
POST/playground/{id}/configure/ebeam/{step}Configure EB: input selection (no catalyst)
PUT/playground/{id}/configure/{step}/editEdit already-configured step (rollback + re-apply)

Capability Intersection

MethodPathWhat It Does
POST/playground/{id}/calculate-intersection/{type}Given selected machine IDs, return only values ALL can produce. Called dynamically when user checks/unchecks machines.

Undo/Redo & Autosave

MethodPathWhat It Does
POST/playground/{id}/undoPop from history stack, push current to redo stack
POST/playground/{id}/redoPop from redo stack, push current to history stack
GET/playground/{id}/historyCan undo? Can redo? Stack sizes.
POST/playground/{id}/autosaveSave session state, mark as saved
GET/playground/{id}/autosave-statusEnabled, interval, seconds since save
PUT/playground/{id}/autosave-settingsToggle enabled, change interval

Validation & Finalization

MethodPathWhat It Does
POST/playground/{id}/validate/{step}Dry-run validation: checks inputs exist, quantities sufficient
POST/playground/{id}/finalizeFinalize design → saves to cable_designs + design_steps + cable_database in one transaction

6.5.4 Machine Configuration Schemas

Each machine type has a Pydantic schema defining its exact form fields in order:

MachineSchemaFields (in order)
Kabatel ÇekmeKabatelCekmeConfigalternative_machines, input_type (fixed), output_diameter, speed, tav, adet, tests
KalaylamaKalaylamaConfigalternative_machines, input_item_id, tin_thickness, speed, adet, tests
İncetel ÇekmeIncetelCekmeConfigalternative_machines, input_item_id, input_number, output_diameter, speed, tav, output_number, tests
BuncherBuncherConfigalternative_machines, inputs (List[BuncherInputBlock]), adet, speed, hatve, twist_direction, tests
ExtruderExtruderConfigalternative_machines, inputs (1+ for twin), insulation_*, sheath_*, speed, tests. No adet (always 1).
E-beamEbeamConfigalternative_machines, input_item_id, tests. Speed/radiation set at production time.

E-beam is design-only: Unlike other machines, E-beam’s speed and radiation_level are not set during design. They are production-time parameters determined by the cable’s material properties. The Playground only records which cable goes through E-beam and assigns tests.

6.5.5 Capability Intersection — Multi-Machine Flexibility

When a user selects multiple alternative machines for a step, the system computes the intersection of their capability ranges. Only values that all selected machines can produce appear in the dropdowns.

# Machine A speed options: [5, 10, 15, 20, 25]
# Machine B speed options: [10, 15, 20, 25, 30]
# Intersection: [10, 15, 20, 25]
# This means any value from the intersection can be
# produced on ANY selected machine → production flexibility

This is called dynamically via POST /calculate-intersection/{machine_type} every time the user checks or unchecks a machine checkbox in the configuration drawer.

6.5.6 Deterministic Code Generation

The CableCodeGenerator ensures that identical products always get the same code, critical for stock management:

Product TypeCode FormatExample
Raw materialRAW_XX_specRAW_COPPER_8MM
Half productMC_specKC_18 (1.8mm wire from Kabatel), BN_73X030 (73-wire bunch)
Final cable{standard}_{item_code}_{id}StandardEnum.EN_EX_4X10X03_3X11X03+INS_07_CAT_DYE+SHT_08_CAT_DYE_6

A SHA256 spec_hash is computed from the full specifications (product_type + machine_type + inputs + outputs + parameters) with sort_keys=True for determinism. If a product with the same hash already exists in product_codes, its existing system_code is returned. Otherwise, a new code is generated with collision-handling (sequence suffix _001, _002, etc.).

6.5.7 Special Cable Types

Twin Cables (Extruder)

Extruder supports multiple inputs for twin/triple cables. Structure uses || separator: (cable1 || cable2)+SHT_0.8mm. Frontend detects twin count from || and generates Turkish names: İkiz, Üçüz, Dördüz, Beşiz.

Multi-Core Cables (Extruder → Buncher → Extruder)

For multi-damar (multi-core) cables, the flow loops: Extruder applies insulation to individual cores, Buncher groups the insulated cores together, then Extruder applies the outer sheath. The system detects this via INS_ patterns in the structure formula.

E-beam Cables (No Catalyst)

E-beam cross-linking replaces chemical catalyst. The form integration completely hides cables with catalyst from the E-beam input dropdown — they are not shown at all, preventing invalid combinations.

6.5.8 Frontend — Playground Page

Main file: src/pages/Teknik/CablePlayground/index.tsx (947 lines) with 7 component files and 1 custom hook.

CablePlayground (index.tsx)

Main orchestrator. Session start modal (standard + cross-section selection), view mode toggle (flow/timeline/code), undo/redo/autosave controls.

FlowCanvas

Visual flow diagram with drag-drop machine placement. Shows production steps as connected nodes.

ConfigurationDrawer

~1,215 lines. The largest component. Opens as a side drawer when configuring a machine. Dynamic forms per machine type. Intersection calculation on machine checkbox change.

ProgressionPanel

Right-side panel showing all items (active/inactive) with quantities, codes, structures. Drives input selection for subsequent steps.

MachineLibrary

Draggable machine palette. 6 machine types with icons and labels.

usePlayground Hook

591 lines. All API integration. Manages session state, loading states, error handling. Bearer token auth via localStorage.

Session Start Flow

Click “Oturum Başlat” Modal: select EN/UL/SLN + cross-section POST /playground/start Canvas appears with 8mm filmaşin in progression

Machine Configuration Flow

Add machine from library POST /steps/add Click machine node on canvas GET /form-data/{type} ConfigurationDrawer opens
Select machines → POST /calculate-intersection Dropdowns update dynamically Fill form → POST /configure/{type}/{step} Progression updates

CRUD Flow

The Playground is not a traditional CRUD page. It is a session-based production simulation engine. The “Create” is a multi-step design process, not a single form submit.

Create (Design a Cable):

  1. Click “Oturum Başlat” (Start Session) → Modal asks for standard (EN/UL/SLN) and cross-section
  2. POST /playground/start → In-memory session created with 8mm filmaşin as initial input in the progression panel
  3. Drag machine from library to canvas → POST /playground/steps/add → step added to session
  4. Click machine node → GET /playground/form-data/{type} → ConfigurationDrawer opens (1,215-line component)
  5. Select real machines (checkboxes) → POST /playground/calculate-intersection → dropdowns update with only values all selected machines can produce
  6. Fill configuration form → POST /playground/configure/{type}/{step} → progression panel updates with new outputs + quantities
  7. Repeat steps 3–6 for each production machine (KC → KL → IC → BN → EX → optional E-beam)
  8. System auto-saves via POST /playground/autosave (every change creates a checkpoint for undo/redo)
  9. Click “Finalize” → POST /playground/finalize → atomic database transaction writes to cable_designs, design_steps, and cable_database tables simultaneously. Deterministic SHA-256 code generated. Session destroyed.

Read (Resume a Session):

  1. Existing sessions persist in memory. Reload the page → GET /playground/status checks for active session
  2. If session exists: canvas restores from last checkpoint with full progression state

Undo / Redo (In-Session):

  1. Click Undo → POST /playground/undo → session restores to previous checkpoint
  2. Click Redo → POST /playground/redo → session advances to next checkpoint
  3. Each configure/add/remove action pushes an atomic checkpoint. Undo stack is unlimited within the session.

Delete (Remove a Step):

  1. Right-click machine node on canvas → “Kaldır” (Remove)
  2. POST /playground/steps/remove → step removed from session, progression recalculated, checkpoint created
  3. Removing a step that has downstream dependents triggers cascading removal of those steps

Why this isn’t traditional CRUD: There is no “edit cable” button after finalization. Once a design is finalized to Cable Database, it is immutable. To “edit” a cable, you start a new Playground session, redesign it, and finalize again. The deterministic code system means if the resulting cable has the same physical specifications, it gets the same code automatically. If it’s different, it gets a new code. This eliminates the risk of modifying a cable that’s already being produced.

6.6 Kablo Veritabanı (Cable Database)

6.6.1 What Gets Saved — The Finalization Process

When the user clicks “Finalize” in the Playground, the system saves three things in one database transaction:

TableWhat Gets Saved
cable_designsDesign metadata: code, name, standard, cross_section, full JSON design_data, approval status, created_by
design_stepsEach production step: step_number, machine_type, parallel_group, machine_ids, inputs/outputs/configuration/tests as JSON
cable_databaseThe finalized cable record: cable_code, cable_type, cross_section, structure_formula, production_flow, half_products, raw_materials, test_requirements (all as JSON)

6.6.2 Database Schema — 4 Tables

cable_designs (375 lines model)

ColumnTypePurpose
idInteger PKUnique ID
design_codeString(50) UNIQUEGenerated code
design_nameString(200)Optional name
standardString(50), CHECK IN (EN, UL, SLN)Cable standard
cross_sectionString(50)e.g. “6mm²”
design_dataText (JSON)Complete session state
is_approvedBooleanAuto-approved in simplified workflow
is_activeBooleanSoft delete
created_by / approved_byInteger FK → usersUser tracking

design_steps

ColumnTypePurpose
idInteger PKUnique ID
design_idInteger FK → cable_designs (CASCADE)Parent design
step_numberIntegerSequential position
is_parallel / parallel_groupBoolean / IntegerParallel processing support
machine_typeString(50)kabatel_cekme, kalaylama, etc.
machine_idsTextComma-separated alternative machine IDs
configurationText (JSON)Full machine config
inputs / outputs / testsText (JSON each)Step I/O and test assignments

Unique constraint: (design_id, step_number, parallel_group)

cable_database — The Core Record

ColumnTypePurpose
idInteger PKUnique ID
design_idInteger FK → cable_designsSource design
cable_codeString(100) UNIQUE, indexedUnique cable identifier used everywhere
standardString(50)EN, UL, SLN
cable_typeString(200)e.g. “EN 6mm² Klasik Kablo”
cross_sectionString(50)e.g. “6mm²”
structure_formulaTextFull structure notation
production_flowText (JSON)Step-by-step production sequence with configs
half_productsText (JSON)All intermediate products with properties
raw_materialsText (JSON)Required raw materials (A=Copper, B=Tin, C=Plastic, D=Catalyst, E=Dye)
test_requirementsText (JSON)Tests assigned at each step with frequencies
is_activeBooleanSoft delete

product_codes — Stock Management Bridge

ColumnTypePurpose
system_codeString(100) UNIQUEHuman-readable code (KC_18, BN_73X030)
spec_hashString(256) UNIQUESHA256 of specifications (deterministic)
product_typeString(50)raw / half / final
machine_typeString(50)Which machine produces it
display_name_tr / enString(200)Turkish/English display names
used_in_designsText (JSON)Array of cable codes using this product
stock_levelFloatCurrent stock quantity

6.6.3 Cable Database API — 15+ Endpoints

MethodPathPermissionWhat It Does
GET/cable-databaseAuthenticatedList cables. Filters: search, cross_section, active_only. Generates display_name with twin/core/layer detection.
GET/cable-database/{code}AuthenticatedSingle cable by code.
GET/cable-database/{code}/fullAuthenticatedComplete raw data for material calculator. Returns half_products with ALL properties.
GET/cable-database/{code}/production-flowAuthenticatedStep-by-step production sequence.
GET/cable-database/{code}/half-productsAuthenticatedAll intermediate products.
GET/cable-database/{code}/requirementsAuthenticatedRaw materials + test requirements.
GET/cable-database/{code}/parsed-structureAuthenticatedStructure parsed into extrusion steps for order forms.
PUT/cable-database/{code}/deactivatesuper_admin, production_managerSoft delete (is_active=false).
DELETE/cable-database/{code}/permanentsuper_adminHard delete cable + related design. Broadcasts real-time update.
GET/products/codesAuthenticatedList all product codes with filters.
GET/products/{code}/usageAuthenticatedWhich cables use this product + stock level.
PUT/products/{code}/stocksuper_admin, production_manager, operatorUpdate stock level.
GET/analytics/common-productsAuthenticatedProducts used in 2+ cables (stock optimization).
GET/analytics/production-efficiencyAuthenticatedReuse %, efficiency score, recommendations.

6.6.4 Frontend — Cable Database Page

Single file: src/pages/Teknik/CableDatabase/index.tsx (691 lines). Route: /teknik/kablo-veritabani.

ProTable

Main data table listing all cables with display_name, cable_code, standard, cross_section, status. Client-side search.

Detail Drawer

Opens when clicking a cable. Tabs: Production Flow (Timeline visualization), Half Products (List), Requirements (raw materials + tests).

ProductionFlowViewer

Ant Design Timeline component showing each production step with machine icons, parameters, and parallel indicators.

CRUD Flow

Cable Database is primarily a read-heavy, write-once store. Cables enter it exclusively via Playground finalization — there is no manual “create cable” form.

Create (via Playground Finalization):

  1. User finalizes a design in Playground → POST /playground/finalize
  2. Backend generates deterministic cable code via SHA-256 hash of physical specifications
  3. If code already exists: finalization is rejected (identical cable already registered)
  4. If code is new: atomic transaction writes cable_designs + design_steps + cable_database rows in one shot
  5. WebSocket broadcast to teknik room → Cable Database table refreshes for all connected users

Read:

  1. Open /teknik/kablo-veritabani → GET /cable-database → ProTable lists all cables with display_name, cable_code, standard, cross_section, status
  2. Client-side search filters by cable code, type, or cross-section
  3. Click a cable row → Detail Drawer opens with three tabs:
    • Production Flow: GET /cable-database/{code}/production-flow → Ant Design Timeline visualization of each production step
    • Half Products: GET /cable-database/{code}/half-products → all intermediate products with properties
    • Requirements: GET /cable-database/{code}/requirements → raw materials (copper, tin, plastic, catalyst, dye) + test requirements
  4. Other modules read cable data via specialized endpoints: /full (material calculator), /parsed-structure (order forms)

Soft Delete (Deactivate):

  1. Click deactivate icon in the table row (requires super_admin or production_manager permission)
  2. Popconfirm warning
  3. PUT /cable-database/{code}/deactivate → sets is_active = false
  4. Cable disappears from default list views (still accessible via active_only=false filter). Downstream modules that reference this cable code still function — deactivation prevents new orders from using it.

Hard Delete (Permanent):

  1. Click permanent delete icon (requires super_admin permission only)
  2. Popconfirm with strong warning text
  3. DELETE /cable-database/{code}/permanent
  4. Backend deletes the cable_database record + related cable_designs + design_steps (cascade)
  5. WebSocket broadcast → table refreshes for all connected users
  6. Danger: This is a destructive operation. If active orders or work cards reference this cable code, those references become orphaned.

Update (Stock Level — Product Codes):

  1. Navigate to product codes view → GET /products/codes
  2. Click stock edit on a product → PUT /products/{code}/stock (requires super_admin, production_manager, or operator)
  3. Updates the stock_level field for that half/final product
  4. No WebSocket broadcast for stock updates — polling-based

Key distinction: Cable Database records themselves are immutable after creation. You cannot edit a cable’s structure, production flow, or material requirements. The only mutable fields are is_active (soft delete toggle) and stock_level on product codes. If a cable design needs modification, a new cable must be designed from scratch in the Playground, which will either generate the same code (if physically identical) or a new one (if different).

6.6.5 How Cable Database Feeds the Rest of the System

→ Sipariş (Order Module)

Order creation fetches cable designs from cable_database. Each order cable stores cable_code. The /parsed-structure endpoint provides extrusion step data for dynamic material selection (plastic, catalyst, dye per layer).

→ Üretim Planlama (Production Planning)

Work card generator reads production_flow and half_products to create work cards for each machine step. The /full endpoint provides complete data for material calculations.

→ Material Calculator

Reads cable_database to calculate raw material quantities (copper kg, plastic kg, tin kg, catalyst kg, dye kg) based on half_products properties (wire_count, wire_groups, bundle_diameter).

→ Stok (Stock Module)

Product codes from cable_database link to stock tracking. Same half product used in multiple cables = shared stock. The used_in_designs array enables cross-cable stock optimization.

→ Global Search

Search module indexes cable_database fields (cable_code, cable_type, cross_section, structure_formula) for system-wide search.

Design principle: The Playground is a production simulation engine, not a drawing tool. It doesn’t just record specifications — it executes the entire manufacturing logic step by step, tracking exact quantities, enforcing machine flow constraints, validating against real machine capabilities, and computing capability intersections. The result is a complete production blueprint stored in Cable Database that every downstream module trusts as the single source of truth. The deterministic code generation ensures identical products always get the same code, enabling stock reuse across different cable designs. The in-memory session architecture with atomic checkpoint/restore guarantees that no partial or invalid state ever reaches the database.

7. CONCLUSION

Teknik is not just a module — it is the foundation on which the entire Solen ERP system stands. Every cable ever produced by the factory begins its life as data defined here. Every order, every work card, every quality test, every material calculation, every stock entry traces back to a record that Teknik created. Without it, the rest of the system has nothing to work with.

7.1 What This Document Covered

This deep dive analyzed the Teknik module across six submodules, from high-level architecture down to individual lines of code:

SectionSubmoduleDepthKey Insight
6.1Machine ManagementFullCapability-range model (min/max/increment) enables dynamic dropdown generation and cross-machine intersection
6.2Standards & TestsFullThree-layer hierarchy (standard → test group → individual test) with multi-standard assignments
6.3Operator ManagementFullDual-storage pattern: integer FK for integrity + denormalized name for display-without-join
6.4MarkalamaFullCross-module data flow: marking_id travels from order → work card → production planning → operator screen
6.5Cable PlaygroundExhaustiveProduction simulation engine with in-memory sessions, atomic checkpoints, quantity tracking, and machine flow constraints
6.6Cable DatabaseExhaustiveSingle source of truth: denormalized JSON blobs enabling zero-join reads for all downstream modules

7.2 Architectural Principles

Several design principles recur throughout the Teknik module and define its character:

Read-Only Downstream

Every other module reads from Teknik but never writes to it. Machines, standards, operators, markings, and cable designs are defined here and consumed everywhere else. This enforces a clean dependency direction.

Simulation Before Storage

The Playground doesn’t accept free-form input. It simulates the real production line: enforce flow constraints, validate against actual machine capabilities, compute intersections, track quantities. Only a fully valid design can be finalized to the database.

Deterministic Identity

SHA-256 spec hashing guarantees that the same physical product always gets the same code, regardless of which cable design created it. This is what makes stock pooling across cable designs possible.

Denormalized for Speed

Cable Database stores production_flow, half_products, raw_materials, and test_requirements as JSON blobs. This is intentional: downstream modules need the complete picture in a single read, not a 12-table join.

7.3 The Numbers

6
SUBMODULES
~75
API ENDPOINTS
12
DATABASE TABLES
~12,000
LINES BACKEND
~4,000
LINES FRONTEND
6
MACHINE TYPES

7.4 How Teknik Feeds the Factory

Teknik Cable Database Sipariş (Orders) Üretim Planlama (Production) Stok & Malzeme (Stock & Materials)

Every cable order references a cable_code from Cable Database. Every work card is generated from the production_flow JSON. Every material calculation reads half_products properties. Every quality test is assigned from the standard hierarchy defined in Teknik. The marking printed on the cable comes from the Markalama submodule. The machines that produce it are validated against capabilities stored in Machine Management.

In short: if Teknik is wrong, everything downstream is wrong. This is why the Playground uses atomic transactions, capability validation, and deterministic code generation — to guarantee that what enters the Cable Database is production-ready and correct.

7.5 Final Word

The Teknik module transforms domain expertise — wire diameters, machine capabilities, production sequences, test standards, marking templates — into structured, validated, machine-readable data. It is the bridge between what engineers know and what software can execute. Every record created here carries the weight of the entire production chain that follows. This document has traced that chain from the first 8mm filmaşin entering Kabatel Çekme to the final cable code stored in the database, through every machine step, every quantity split, every validation check, and every downstream consumer. The system works because Teknik is thorough. This document exists to prove it.