diff --git a/Admin/Install/Media.install.json b/Admin/Install/Media.install.json new file mode 100644 index 0000000..3b1bf61 --- /dev/null +++ b/Admin/Install/Media.install.json @@ -0,0 +1,30 @@ +[ + { + "type": "type", + "name": "equipment_profile_image", + "l11n": [ + { + "title": "Profile image", + "lang": "en" + }, + { + "title": "Profilbild", + "lang": "de" + } + ] + }, + { + "type": "collection", + "create_directory": true, + "name": "AssetManagement", + "virtualPath": "/Modules", + "user": 1 + }, + { + "type": "collection", + "create_directory": true, + "name": "Asset", + "virtualPath": "/Modules/AssetManagement", + "user": 1 + } +] \ No newline at end of file diff --git a/Admin/Install/Media.php b/Admin/Install/Media.php new file mode 100644 index 0000000..9839d76 --- /dev/null +++ b/Admin/Install/Media.php @@ -0,0 +1,43 @@ + __DIR__ . '/Media.install.json']); + } +} diff --git a/Admin/Install/Navigation.install.json b/Admin/Install/Navigation.install.json index 33b959a..2ebedd9 100644 --- a/Admin/Install/Navigation.install.json +++ b/Admin/Install/Navigation.install.json @@ -27,6 +27,36 @@ "permission": { "permission": 2, "type": null, "element": null }, "parent": 1006601001, "children": [] + }, + { + "id": 1006603001, + "pid": "/accounting/asset", + "type": 3, + "subtype": 1, + "name": "Table", + "uri": "{/base}/accounting/asset/table", + "target": "self", + "icon": null, + "order": 1, + "from": "AssetManagement", + "permission": { "permission": 2, "type": null, "element": null }, + "parent": 1006601001, + "children": [] + }, + { + "id": 1006604001, + "pid": "/accounting/asset", + "type": 3, + "subtype": 1, + "name": "Entries", + "uri": "{/base}/accounting/asset/entry/list", + "target": "self", + "icon": null, + "order": 15, + "from": "AssetManagement", + "permission": { "permission": 2, "type": null, "element": null }, + "parent": 1006601001, + "children": [] } ] } diff --git a/Admin/Install/assettype.json b/Admin/Install/assettype.json new file mode 100644 index 0000000..b7503f8 --- /dev/null +++ b/Admin/Install/assettype.json @@ -0,0 +1,1610 @@ +[ + { + "industry": 0, + "duration": 168, + "l11n": { + "en": "Halls in lightweight construction", + "de": "Hallen in Leichtbauweise" + } + }, + { + "industry": 0, + "duration": 240, + "l11n": { + "en": "Tennis halls, squash courts, etc.", + "de": "Tennishallen, Squashhallen u.ä." + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Air domes", + "de": "Traglufthallen" + } + }, + { + "industry": 0, + "duration": 240, + "l11n": { + "en": "Cold storage halls", + "de": "Kühlhallen" + } + }, + { + "industry": 0, + "duration": 192, + "l11n": { + "en": "Barracks and sheds", + "de": "Baracken und Schuppen" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Construction huts", + "de": "Baubuden" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Beer tents", + "de": "Bierzelte" + } + }, + { + "industry": 0, + "duration": 240, + "l11n": { + "en": "Pump houses, transformer station houses and switch houses", + "de": "Pumpenhäuser, Trafostationshäuser und Schalthäuser" + } + }, + { + "industry": 0, + "duration": 396, + "l11n": { + "en": "Concrete silo buildings", + "de": "Silobauten aus Beton" + } + }, + { + "industry": 0, + "duration": 300, + "l11n": { + "en": "Steel silo buildings", + "de": "Silobauten aus Stahl" + } + }, + { + "industry": 0, + "duration": 204, + "l11n": { + "en": "Plastic silo buildings", + "de": "Silobauten aus Kunststoff" + } + }, + { + "industry": 0, + "duration": 396, + "l11n": { + "en": "Masonry or concrete chimneys", + "de": "Schornsteine aus Mauerwerk oder Beton" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Metal chimneys", + "de": "Schornsteine aus Metall" + } + }, + { + "industry": 0, + "duration": 300, + "l11n": { + "en": "Loading ramps", + "de": "Laderampen" + } + }, + { + "industry": 0, + "duration": 228, + "l11n": { + "en": "Roadways, parking lots and yard pavements with packing layer", + "de": "Fahrbahnen, Parkplätze und Hofbefestigungen mit Packlage" + } + }, + { + "industry": 0, + "duration": 108, + "l11n": { + "en": "Roadways, parking lots and yard pavements in gravel, crushed stone, slag", + "de": "Fahrbahnen, Parkplätze und Hofbefestigungen in Kies, Schotter, Schlacken" + } + }, + { + "industry": 0, + "duration": 396, + "l11n": { + "en": "Road and path bridges made of steel and concrete", + "de": "Strafen- und Wegebrücken aus Stahl und Beton" + } + }, + { + "industry": 0, + "duration": 180, + "l11n": { + "en": "Road and path bridges made of wood", + "de": "Strafen- und Wegebrücken aus Holz" + } + }, + { + "industry": 0, + "duration": 60, + "l11n": { + "en": "Wooden fencing", + "de": "Umzäunungen aus Holz" + } + }, + { + "industry": 0, + "duration": 204, + "l11n": { + "en": "Fencing Other", + "de": "Umzäunungen Sonstige" + } + }, + { + "industry": 0, + "duration": 228, + "l11n": { + "en": "Outdoor lighting, street lighting", + "de": "Aufenbeleuchtung, Strafenbeleuchtung" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Orientation systems, sign bridges", + "de": "Orientierungssysteme, Schilderbrücken" + } + }, + { + "industry": 0, + "duration": 240, + "l11n": { + "en": "Bank reinforcements", + "de": "Uferbefestigungen" + } + }, + { + "industry": 0, + "duration": 240, + "l11n": { + "en": "Fountains", + "de": "Brunnen" + } + }, + { + "industry": 0, + "duration": 396, + "l11n": { + "en": "Concrete or masonry drainage systems", + "de": "Drainagen aus Beton oder Mauerwerk" + } + }, + { + "industry": 0, + "duration": 156, + "l11n": { + "en": "Clay or plastic drainage systems", + "de": "Drainagen aus Ton oder Kunststoff" + } + }, + { + "industry": 0, + "duration": 240, + "l11n": { + "en": "Sewage treatment plants with inlet and outlet", + "de": "Kläranlagen m. Zu- und Ableitung" + } + }, + { + "industry": 0, + "duration": 240, + "l11n": { + "en": "Fire water ponds", + "de": "Löschwasserteiche" + } + }, + { + "industry": 0, + "duration": 240, + "l11n": { + "en": "Water reservoirs", + "de": "Wasserspeicher" + } + }, + { + "industry": 0, + "duration": 180, + "l11n": { + "en": "Green spaces", + "de": "Grünanlagen" + } + }, + { + "industry": 0, + "duration": 240, + "l11n": { + "en": "Golf courses", + "de": "Golfplätze" + } + }, + { + "industry": 0, + "duration": 180, + "l11n": { + "en": "Steam generation (steam boilers with accessories)", + "de": "Dampferzeugung (Dampfkessel mit Zubehör)" + } + }, + { + "industry": 0, + "duration": 228, + "l11n": { + "en": "Power generation (rectifiers, charging units, emergency power generators, power generators, power converters, etc.)", + "de": "Stromerzeugung (Gleichrichter, Ladeaggregate, Notstromaggregate, Stromgeneratoren, Stromumformer usw.)" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Accumulators", + "de": "Akkumulatoren" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Combined heat and power plants (cogeneration plants)", + "de": "Kraft-Wärmekopplungsanlagen (Blockheizkraftwerke)" + } + }, + { + "industry": 0, + "duration": 192, + "l11n": { + "en": "Wind power plants", + "de": "Windkraftanlagen" + } + }, + { + "industry": 0, + "duration": 240, + "l11n": { + "en": "Photovoltaic systems", + "de": "Photovoltaikanlagen" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "solar systems", + "de": "Solaranlagen" + } + }, + { + "industry": 0, + "duration": 168, + "l11n": { + "en": "Hot air, refrigeration systems, compressors, fans, etc.", + "de": "Heifluft-, Kälteanlagen, Kompressoren, Ventilatoren usw." + } + }, + { + "industry": 0, + "duration": 180, + "l11n": { + "en": "Boilers incl. pressure boilers", + "de": "Kessel einschl. Druckkessel" + } + }, + { + "industry": 0, + "duration": 144, + "l11n": { + "en": "Water treatment plants", + "de": "Wasseraufbereitungsanlagen" + } + }, + { + "industry": 0, + "duration": 144, + "l11n": { + "en": "Water softening systems", + "de": "Wasserenthärtungsanlagen" + } + }, + { + "industry": 0, + "duration": 132, + "l11n": { + "en": "Water purification systems", + "de": "Wasserreinigungsanlagen" + } + }, + { + "industry": 0, + "duration": 144, + "l11n": { + "en": "Compressed air systems", + "de": "Druckluftanlagen" + } + }, + { + "industry": 0, + "duration": 180, + "l11n": { + "en": "Heat exchangers", + "de": "Wärmetauscher" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Recovery systems", + "de": "Rückgewinnungsanlagen" + } + }, + { + "industry": 0, + "duration": 216, + "l11n": { + "en": "Measuring and control equipment in general", + "de": "Mess- und Regeleinrichtungen allgemein" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Emission measuring devices", + "de": "Emissionsmessgeräte" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Material testing devices", + "de": "Materialprüfgeräte" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Ultrasonic devices (non-medical)", + "de": "Ultraschallgeräte (nicht medizinisch)" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Electronic surveying equipment", + "de": "Vermessungsgeräte elektronisch" + } + }, + { + "industry": 0, + "duration": 144, + "l11n": { + "en": "Mechanical measuring devices", + "de": "Vermessungsgeräte mechanisch" + } + }, + { + "industry": 0, + "duration": 168, + "l11n": { + "en": "Elevators, screw conveyors, roller conveyors, overhead conveyors, conveyor belts, conveyor belts and apron conveyors", + "de": "Elevatoren, Förderschnecken, Rollenbahnen, Hängebahnen, Transportbänder, Förderbänder und Plattenbänder" + } + }, + { + "industry": 0, + "duration": 396, + "l11n": { + "en": "Track systems with turntables, switches, signaling systems, etc. in accordance with legal regulations", + "de": "Gleisanlagen mit Drehscheiben, Weichen, Signalanlagen u.ä. nach gesetzlichen Vorschriften" + } + }, + { + "industry": 0, + "duration": 180, + "l11n": { + "en": "Track systems with turntables, switches, signaling systems, etc. other", + "de": "Gleisanlagen mit Drehscheiben, Weichen, Signalanlagen u.ä. sonstige" + } + }, + { + "industry": 0, + "duration": 252, + "l11n": { + "en": "Crane systems fixed or on rails", + "de": "Krananlagen ortsfest oder auf Schienen" + } + }, + { + "industry": 0, + "duration": 168, + "l11n": { + "en": "Other crane systems", + "de": "Krananlagen sonstige" + } + }, + { + "industry": 0, + "duration": 180, + "l11n": { + "en": "Elevators, winches, working platforms, lifting platforms, scaffolding, stationary lifts", + "de": "Aufzüge, Winden, Arbeitsbühnen, Hebebühnen, Gerüste, Hublifte stationär" + } + }, + { + "industry": 0, + "duration": 132, + "l11n": { + "en": "Elevators, winches, work platforms, lifting platforms, scaffolding, mobile lifts", + "de": "Aufzüge, Winden, Arbeitsbühnen, Hebebühnen, Gerüste, Hublifte mobil" + } + }, + { + "industry": 0, + "duration": 180, + "l11n": { + "en": "High-bay warehouse", + "de": "Hochregallager" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Transport containers, construction containers, office containers and residential containers", + "de": "Transportcontainer, Baucontainer, Bürocontainer und Wohncontainer" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Store fittings, restaurant fittings Shop window systems and fittings", + "de": "Ladeneinbauten, Gaststätteneinbauten Schaufensteranlagen u. -einbauten" + } + }, + { + "industry": 0, + "duration": 108, + "l11n": { + "en": "illuminated advertising", + "de": "Lichtreklame" + } + }, + { + "industry": 0, + "duration": 108, + "l11n": { + "en": "Showcases, display cases", + "de": "Schaukästen, Vitrinen" + } + }, + { + "industry": 0, + "duration": 240, + "l11n": { + "en": "weighbridges", + "de": "Brückenwaagen" + } + }, + { + "industry": 0, + "duration": 168, + "l11n": { + "en": "Tank and dispensing systems for fuels and lubricants", + "de": "Tank- und Zapfanlagen für Treib- und Schmierstoffe" + } + }, + { + "industry": 0, + "duration": 300, + "l11n": { + "en": "Fuel tanks", + "de": "Brennstofftanks" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Car washes", + "de": "Autowaschanlagen" + } + }, + { + "industry": 0, + "duration": 168, + "l11n": { + "en": "Fume extractors, dust extraction systems", + "de": "Abzugsvorrichtungen, Entstaubungsvorrichtungen" + } + }, + { + "industry": 0, + "duration": 132, + "l11n": { + "en": "Alarm and monitoring systems", + "de": "Alarmanlagen und cberwachungsanlagen" + } + }, + { + "industry": 0, + "duration": 240, + "l11n": { + "en": "Sprinkler systems", + "de": "Sprinkleranlagen" + } + }, + { + "industry": 0, + "duration": 300, + "l11n": { + "en": "Rail vehicles", + "de": "Schienenfahrzeuge" + } + }, + { + "industry": 0, + "duration": 72, + "l11n": { + "en": "Passenger cars and station wagons", + "de": "Personenkraftwagen und Kombiwagen" + } + }, + { + "industry": 0, + "duration": 84, + "l11n": { + "en": "Motorcycles, scooters, bicycles, etc.", + "de": "Motorräder, Motorroller, Fahrräder u.ä." + } + }, + { + "industry": 0, + "duration": 108, + "l11n": { + "en": "Trucks, articulated lorries, tippers", + "de": "Lastkraftwagen, Sattelschlepper, Kipper" + } + }, + { + "industry": 0, + "duration": 144, + "l11n": { + "en": "Tractors and tractors", + "de": "Traktoren und Schlepper" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Small tractors", + "de": "Kleintraktoren" + } + }, + { + "industry": 0, + "duration": 132, + "l11n": { + "en": "Trailers, semi-trailers, swap bodies", + "de": "Anhänger, Auflieger, Wechselaufbauten" + } + }, + { + "industry": 0, + "duration": 108, + "l11n": { + "en": "Buses and coaches", + "de": "Omnibusse" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Fire engines", + "de": "Feuerwehrfahrzeuge" + } + }, + { + "industry": 0, + "duration": 72, + "l11n": { + "en": "Rescue vehicles and ambulances", + "de": "Rettungsfahrzeuge und Krankentransportfahrzeuge" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Motorhomes, caravans", + "de": "Wohnmobile, Wohnwagen" + } + }, + { + "industry": 0, + "duration": 144, + "l11n": { + "en": "construction trailers", + "de": "Bauwagen" + } + }, + { + "industry": 0, + "duration": 252, + "l11n": { + "en": "Aircraft under 20 tons maximum permissible flight weight", + "de": "Flugzeuge unter 20 t höchstzulässigem Fluggewicht" + } + }, + { + "industry": 0, + "duration": 228, + "l11n": { + "en": "Rotorcraft (helicopters)", + "de": "Drehflügler (Hubschrauber)" + } + }, + { + "industry": 0, + "duration": 60, + "l11n": { + "en": "Hot air balloons", + "de": "Heifluftballone" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Airships", + "de": "Luftschiffe" + } + }, + { + "industry": 0, + "duration": 240, + "l11n": { + "en": "launches", + "de": "Barkassen" + } + }, + { + "industry": 0, + "duration": 360, + "l11n": { + "en": "pontoons", + "de": "Pontons" + } + }, + { + "industry": 0, + "duration": 240, + "l11n": { + "en": "sailing yachts", + "de": "Segelyachten" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Other means of transportation (electric carts, forklifts, pallet trucks, etc.)", + "de": "sonstige Beförderungsmittel (Elektrokarren, Stapler, Hubwagen usw.)" + } + }, + { + "industry": 0, + "duration": 156, + "l11n": { + "en": "dressing machines", + "de": "Abrichtmaschinen" + } + }, + { + "industry": 0, + "duration": 156, + "l11n": { + "en": "bending machines", + "de": "Biegemaschinen" + } + }, + { + "industry": 0, + "duration": 192, + "l11n": { + "en": "Stationary drilling machines", + "de": "Bohrmaschinen stationär" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Mobile drilling machines", + "de": "Bohrmaschinen mobil" + } + }, + { + "industry": 0, + "duration": 84, + "l11n": { + "en": "Drill hammers and pneumatic hammers", + "de": "Bohrhämmer und Presslufthämmer" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Brushing machines", + "de": "Bürstmaschinen" + } + }, + { + "industry": 0, + "duration": 192, + "l11n": { + "en": "Lathes", + "de": "Drehbänke" + } + }, + { + "industry": 0, + "duration": 180, + "l11n": { + "en": "Stationary milling machines", + "de": "Fräsmaschinen stationär" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Mobile milling machines", + "de": "Fräsmaschinen mobil" + } + }, + { + "industry": 0, + "duration": 84, + "l11n": { + "en": "Spark erosion machines", + "de": "Funkenerosionsmaschinen" + } + }, + { + "industry": 0, + "duration": 192, + "l11n": { + "en": "Planing machines stationary", + "de": "Hobelmaschinen stationär" + } + }, + { + "industry": 0, + "duration": 108, + "l11n": { + "en": "Mobile planing machines", + "de": "Hobelmaschinen mobil" + } + }, + { + "industry": 0, + "duration": 156, + "l11n": { + "en": "Polishing machines stationary", + "de": "Poliermaschinen stationär" + } + }, + { + "industry": 0, + "duration": 60, + "l11n": { + "en": "Mobile polishing machines", + "de": "Poliermaschinen mobil" + } + }, + { + "industry": 0, + "duration": 168, + "l11n": { + "en": "Presses and punching machines", + "de": "Pressen und Stanzen" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Upsetting machines", + "de": "Stauchmaschinen" + } + }, + { + "industry": 0, + "duration": 132, + "l11n": { + "en": "Tampers and vibrating plates", + "de": "Stampfer und Rüttelplatten" + } + }, + { + "industry": 0, + "duration": 168, + "l11n": { + "en": "All types of stationary saws", + "de": "Sägen aller Art stationär" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "All types of mobile saws", + "de": "Sägen aller Art mobil" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Stationary cut-off machines", + "de": "Trennmaschinen stationär" + } + }, + { + "industry": 0, + "duration": 84, + "l11n": { + "en": "Mobile cutting machines", + "de": "Trennmaschinen mobil" + } + }, + { + "industry": 0, + "duration": 108, + "l11n": { + "en": "Sandblasting blowers", + "de": "Sandstrahlgebläse" + } + }, + { + "industry": 0, + "duration": 180, + "l11n": { + "en": "Stationary sanding machines", + "de": "Schleifmaschinen stationär" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Mobile grinding machines", + "de": "Schleifmaschinen mobil" + } + }, + { + "industry": 0, + "duration": 156, + "l11n": { + "en": "Cutting machines and shears stationary", + "de": "Schneidemaschinen und Scheren stationär" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Cutting machines and shears mobile", + "de": "Schneidemaschinen und Scheren mobil" + } + }, + { + "industry": 0, + "duration": 72, + "l11n": { + "en": "Shredders", + "de": "Shredder" + } + }, + { + "industry": 0, + "duration": 156, + "l11n": { + "en": "Welding and soldering equipment", + "de": "Schweifgeräte und Lötgeräte" + } + }, + { + "industry": 0, + "duration": 156, + "l11n": { + "en": "Injection molding machines", + "de": "Spritzgussmaschinen" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Filling machines", + "de": "Abfüllanlagen" + } + }, + { + "industry": 0, + "duration": 156, + "l11n": { + "en": "Packaging machines, film sealers", + "de": "Verpackungsmaschinen, Folienschweifgeräte" + } + }, + { + "industry": 0, + "duration": 144, + "l11n": { + "en": "Collating machines", + "de": "Zusammentragmaschinen" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Stamping machines", + "de": "Stempelmaschinen" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Banding machines", + "de": "Banderoliermaschinen" + } + }, + { + "industry": 0, + "duration": 156, + "l11n": { + "en": "Other processing and finishing machines (bending, gluing, pointing, etching, coating, printing, anodizing, degreasing, deburring, eroding, labelling, folding, dyeing, filing, casting, electroplating, engraving, hardening, stapling, painting, riveting)", + "de": "Sonstige Be- und Verarbeitungsmaschinen (Abkanten, Anleimen, Anspitzen, Ätzen, Beschichten, Drucken, Eloxieren, Entfetten, Entgraten, Erodieren, Etikettieren, Falzen, Färben, Feilen, Giefen, Galvanisieren, Gravieren, Härten, Heften, Lackieren, Nieten)" + } + }, + { + "industry": 0, + "duration": 168, + "l11n": { + "en": "Economic goods of workshop, laboratory and storage equipment", + "de": "Wirtschaftsgüter der Werkstätten-, Labor- und Lagereinrichtungen" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Store equipment assets", + "de": "Wirtschaftsgüter der Ladeneinrichtungen" + } + }, + { + "industry": 0, + "duration": 72, + "l11n": { + "en": "Exhibition stands", + "de": "Messestände" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Refrigeration equipment", + "de": "Kühleinrichtungen" + } + }, + { + "industry": 0, + "duration": 132, + "l11n": { + "en": "Air conditioners (mobile)", + "de": "Klimageräte (mobil)" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Ventilation units, air extraction units (mobile)", + "de": "Belüftungsgeräte, Entlüftungsgeräte (mobil)" + } + }, + { + "industry": 0, + "duration": 60, + "l11n": { + "en": "Grease separators", + "de": "Fettabscheider" + } + }, + { + "industry": 0, + "duration": 72, + "l11n": { + "en": "Magnetic separators", + "de": "Magnetabscheider" + } + }, + { + "industry": 0, + "duration": 60, + "l11n": { + "en": "Wet separators", + "de": "Nassabscheider" + } + }, + { + "industry": 0, + "duration": 132, + "l11n": { + "en": "Hot air blowers, cold air blowers (mobile)", + "de": "Heifluftgebläse, Kaltluftgebläse (mobil)" + } + }, + { + "industry": 0, + "duration": 108, + "l11n": { + "en": "Space heaters (mobile)", + "de": "Raumheizgeräte (mobil)" + } + }, + { + "industry": 0, + "duration": 72, + "l11n": { + "en": "Work tents", + "de": "Arbeitszelte" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Telephone exchange systems", + "de": "Fernsprechnebenstellenanlagen" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "General communication terminals", + "de": "Kommunikationsendgeräte Allgemein" + } + }, + { + "industry": 0, + "duration": 60, + "l11n": { + "en": "Mobile radio terminals", + "de": "Mobilfunkendgeräte" + } + }, + { + "industry": 0, + "duration": 72, + "l11n": { + "en": "Text terminals (fax machines, etc.)", + "de": "Textendeinrichtungen (Faxgeräte u.ä.)" + } + }, + { + "industry": 0, + "duration": 132, + "l11n": { + "en": "Company radio systems", + "de": "Betriebsfunkanlagen" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Antenna masts", + "de": "Antennenmasten" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Addressing machines, enveloping machines, franking machines", + "de": "Adressiermaschinen, Kuvertiermaschinen, Frankiermaschinen" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Pagination machines", + "de": "Paginiermaschinen" + } + }, + { + "industry": 0, + "duration": 84, + "l11n": { + "en": "Mainframe computers", + "de": "Grofrechner" + } + }, + { + "industry": 0, + "duration": 36, + "l11n": { + "en": "Workstations, personal computers, notebooks and their peripherals (printers, scanners, monitors, etc.)", + "de": "Workstations, Personalcomputer, Notebooks und deren Peripheriegeräte (Drucker, Scanner, Bildschirme u.ä.)" + } + }, + { + "industry": 0, + "duration": 84, + "l11n": { + "en": "Photo, film, video and audio equipment (televisions, CD players, recorders, loudspeakers, radios, amplifiers, cameras, monitors, etc.)", + "de": "Foto-, Film-, Video- und Audiogeräte (Fernseher, CD-Player, Recorder, Lautsprecher, Verstärker, Kameras, Monitore u.ä.)" + } + }, + { + "industry": 0, + "duration": 108, + "l11n": { + "en": "Public address systems", + "de": "Beschallungsanlagen" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Presentation devices, data display devices", + "de": "Präsentationsgeräte, Datensichtgeräte" + } + }, + { + "industry": 0, + "duration": 72, + "l11n": { + "en": "cash registers", + "de": "Registrierkassen" + } + }, + { + "industry": 0, + "duration": 108, + "l11n": { + "en": "Typewriters", + "de": "Schreibmaschinen" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Electronic drawing equipment", + "de": "Zeichengeräte elektronisch" + } + }, + { + "industry": 0, + "duration": 168, + "l11n": { + "en": "Mechanical drawing machines", + "de": "Zeichengeräte mechanisch" + } + }, + { + "industry": 0, + "duration": 84, + "l11n": { + "en": "Duplicating machines", + "de": "Vervielfältigungsgeräte" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Time recording devices", + "de": "Zeiterfassungsgeräte" + } + }, + { + "industry": 0, + "duration": 84, + "l11n": { + "en": "Money validators, money sorters, money changers and money counters", + "de": "Geldprüfgeräte, Geldsortiergeräte, Geldwechselgeräte und Geldzählgeräte" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Shredders (document shredders)", + "de": "Reifwölfe (Aktenvernichter)" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Card readers (EC, credit)", + "de": "Kartenleser (EC-, Kredit-)" + } + }, + { + "industry": 0, + "duration": 156, + "l11n": { + "en": "Office furniture", + "de": "Büromöbel" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Sales counters", + "de": "Verkaufstheken" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Sales booths, sales stands", + "de": "Verkaufsbuden, Verkaufsstände" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Plantings in buildings", + "de": "Bepflanzungen in Gebäuden" + } + }, + { + "industry": 0, + "duration": 168, + "l11n": { + "en": "Steel cabinets", + "de": "Stahlschränke" + } + }, + { + "industry": 0, + "duration": 276, + "l11n": { + "en": "Armored cabinets, safes", + "de": "Panzerschränke, Tresore" + } + }, + { + "industry": 0, + "duration": 300, + "l11n": { + "en": "Safe systems", + "de": "Tresoranlagen" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Carpets normal", + "de": "Teppiche normale" + } + }, + { + "industry": 0, + "duration": 180, + "l11n": { + "en": "High-quality carpets (from DM 1,000\/m2)", + "de": "Teppiche hochwertige (ab 1.000 DM\/m2)" + } + }, + { + "industry": 0, + "duration": 180, + "l11n": { + "en": "Works of art (excluding works by recognized artists)", + "de": "Kunstwerke (ohne Werke anerkannter Künstler)" + } + }, + { + "industry": 0, + "duration": 132, + "l11n": { + "en": "Scales (fruit, vegetable, meat, etc.)", + "de": "Waagen (Obst-, Gemüse-, Fleisch- u.ä.)" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "pneumatic tube systems", + "de": "Rohrpostanlagen" + } + }, + { + "industry": 0, + "duration": 72, + "l11n": { + "en": "Small concrete mixers", + "de": "Betonkleinmischer" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "floor polishers", + "de": "Bohnermaschinen" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Disinfection devices", + "de": "Desinfektionsgeräte" + } + }, + { + "industry": 0, + "duration": 84, + "l11n": { + "en": "Dishwashers and glasswashers", + "de": "Geschirr- und Gläserspülmaschinen" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "High-pressure cleaners (steam and water)", + "de": "Hochdruckreiniger (Dampf- und Wasser-)" + } + }, + { + "industry": 0, + "duration": 84, + "l11n": { + "en": "Industrial vacuum cleaners", + "de": "Industriestaubsauger" + } + }, + { + "industry": 0, + "duration": 108, + "l11n": { + "en": "Sweepers", + "de": "Kehrmaschinen" + } + }, + { + "industry": 0, + "duration": 108, + "l11n": { + "en": "Sweepers", + "de": "Räumgeräte" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Sterilizers", + "de": "Sterilisatoren" + } + }, + { + "industry": 0, + "duration": 84, + "l11n": { + "en": "Carpet cleaners (portable)", + "de": "Teppichreinigungsgeräte (transportabel)" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Washing machines", + "de": "Waschmaschinen" + } + }, + { + "industry": 0, + "duration": 60, + "l11n": { + "en": "Building drying and dehumidifying appliances", + "de": "Bautrocknungs- und Entfeuchtungsgeräte" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Tumble dryers", + "de": "Wäschetrockner" + } + }, + { + "industry": 0, + "duration": 84, + "l11n": { + "en": "Beverage vending machines, reverse vending machines", + "de": "Getränkeautomaten, Leergutautomaten" + } + }, + { + "industry": 0, + "duration": 60, + "l11n": { + "en": "Vending machines", + "de": "Warenautomaten" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Cigarette vending machines", + "de": "Zigarettenautomaten" + } + }, + { + "industry": 0, + "duration": 60, + "l11n": { + "en": "Passport photo machines", + "de": "Passbildautomaten" + } + }, + { + "industry": 0, + "duration": 60, + "l11n": { + "en": "Business card machines", + "de": "Visitenkartenautomaten" + } + }, + { + "industry": 0, + "duration": 48, + "l11n": { + "en": "Gambling machines (machines with the possibility of winning)", + "de": "Geldspielgeräte (Spielgeräte mit Gewinnmöglichkeit)" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Music machines", + "de": "Musikautomaten" + } + }, + { + "industry": 0, + "duration": 72, + "l11n": { + "en": "video machines", + "de": "Videoautomaten" + } + }, + { + "industry": 0, + "duration": 60, + "l11n": { + "en": "Other amusement machines (e.g. pinball machines)", + "de": "sonstige Unterhaltungsautomaten (z.B. Flipper)" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "flagpoles", + "de": "Fahnenmasten" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "refrigerators", + "de": "Kühlschränke" + } + }, + { + "industry": 0, + "duration": 156, + "l11n": { + "en": "Laboratory equipment (microscopes, precision balances, etc.)", + "de": "Laborgeräte (Mikroskope, Präzisionswaagen u.ä.)" + } + }, + { + "industry": 0, + "duration": 96, + "l11n": { + "en": "Microwave ovens", + "de": "Mikrowellengeräte" + } + }, + { + "industry": 0, + "duration": 108, + "l11n": { + "en": "Lawn mowers", + "de": "Rasenmäher" + } + }, + { + "industry": 0, + "duration": 108, + "l11n": { + "en": "Toilet cubicles and toilet trailers", + "de": "Toilettenkabinen und Toilettenwagen" + } + }, + { + "industry": 0, + "duration": 120, + "l11n": { + "en": "Centrifuges", + "de": "Zentrifugen" + } + } +] \ No newline at end of file diff --git a/Admin/Install/attributes.json b/Admin/Install/attributes.json new file mode 100644 index 0000000..4ddd4b7 --- /dev/null +++ b/Admin/Install/attributes.json @@ -0,0 +1,178 @@ +[ + { + "name": "is_gauge", + "l11n": { + "en": "Gauge", + "de": "Messgerät" + }, + "value_type": 1, + "is_custom_allowed": false, + "validation_pattern": "", + "is_required": false, + "default_value": "", + "values": [ + { + "value": 0 + }, + { + "value": 1 + } + ] + }, + { + "name": "insurance_provider", + "l11n": { + "en": "Insurance provider", + "de": "Versicherung" + }, + "value_type": 2, + "is_custom_allowed": true, + "validation_pattern": "", + "is_required": false, + "default_value": "", + "values": [] + }, + { + "name": "insurance_number", + "l11n": { + "en": "Insurance number", + "de": "Versicherungsnummer" + }, + "value_type": 2, + "is_custom_allowed": true, + "validation_pattern": "", + "is_required": false, + "default_value": "", + "values": [] + }, + { + "name": "leasing_provider", + "l11n": { + "en": "Leasing provider", + "de": "Leasingsnummer" + }, + "value_type": 2, + "is_custom_allowed": true, + "validation_pattern": "", + "is_required": false, + "default_value": "", + "values": [] + }, + { + "name": "leasing_number", + "l11n": { + "en": "Leasing number", + "de": "Leasingsnummer" + }, + "value_type": 2, + "is_custom_allowed": true, + "validation_pattern": "", + "is_required": false, + "default_value": "", + "values": [] + }, + { + "name": "leasing_end", + "l11n": { + "en": "Leasing end", + "de": "Leasingende" + }, + "value_type": 4, + "is_custom_allowed": true, + "validation_pattern": "", + "is_required": false, + "default_value": "", + "values": [] + }, + { + "name": "make", + "l11n": { + "en": "Make", + "de": "Marke" + }, + "value_type": 2, + "is_custom_allowed": true, + "validation_pattern": "", + "is_required": false, + "default_value": "", + "values": [] + }, + { + "name": "model", + "l11n": { + "en": "Model", + "de": "Modell" + }, + "value_type": 2, + "is_custom_allowed": true, + "validation_pattern": "", + "is_required": false, + "default_value": "", + "values": [] + }, + { + "name": "build", + "l11n": { + "en": "Build year", + "de": "Baujahr" + }, + "value_type": 4, + "is_custom_allowed": true, + "validation_pattern": "", + "is_required": false, + "default_value": "", + "values": [] + }, + { + "name": "ownership_start", + "l11n": { + "en": "Ownership start", + "de": "Besitzbeginn" + }, + "value_type": 4, + "is_custom_allowed": true, + "validation_pattern": "", + "is_required": false, + "default_value": "", + "values": [] + }, + { + "name": "ownership_end", + "l11n": { + "en": "Ownership end", + "de": "Besitzende" + }, + "value_type": 4, + "is_custom_allowed": true, + "validation_pattern": "", + "is_required": false, + "default_value": "", + "values": [] + }, + { + "name": "purchase_price", + "l11n": { + "en": "Purchase price", + "de": "Kaufpreis" + }, + "value_type": 1, + "is_custom_allowed": true, + "validation_pattern": "", + "is_required": false, + "default_value": "", + "values": [] + }, + { + "name": "leasing_residual_value", + "l11n": { + "en": "Leasing residual value", + "de": "Leasing Restwert" + }, + "value_type": 1, + "is_custom_allowed": true, + "validation_pattern": "", + "is_required": false, + "default_value": "", + "values": [] + } +] \ No newline at end of file diff --git a/Admin/Install/db.json b/Admin/Install/db.json new file mode 100644 index 0000000..1330d6c --- /dev/null +++ b/Admin/Install/db.json @@ -0,0 +1,400 @@ +{ + "assetmgmt_asset_type": { + "name": "assetmgmt_asset_type", + "fields": { + "assetmgmt_asset_type_id": { + "name": "assetmgmt_asset_type_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "assetmgmt_asset_type_name": { + "name": "assetmgmt_asset_type_name", + "type": "VARCHAR(255)", + "null": false + }, + "assetmgmt_asset_type_depreciation_duration": { + "name": "assetmgmt_asset_type_depreciation_duration", + "type": "INT", + "null": false + }, + "assetmgmt_asset_type_industry": { + "name": "assetmgmt_asset_type_industry", + "type": "INT", + "null": false + } + } + }, + "assetmgmt_asset_type_l11n": { + "name": "assetmgmt_asset_type_l11n", + "fields": { + "assetmgmt_asset_type_l11n_id": { + "name": "assetmgmt_asset_type_l11n_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "assetmgmt_asset_type_l11n_title": { + "name": "assetmgmt_asset_type_l11n_title", + "type": "VARCHAR(255)", + "null": false + }, + "assetmgmt_asset_type_l11n_type": { + "name": "assetmgmt_asset_type_l11n_type", + "type": "INT(11)", + "null": false, + "foreignTable": "assetmgmt_asset_type", + "foreignKey": "assetmgmt_asset_type_id" + }, + "assetmgmt_asset_type_l11n_lang": { + "name": "assetmgmt_asset_type_l11n_lang", + "type": "VARCHAR(2)", + "null": false, + "foreignTable": "language", + "foreignKey": "language_639_1" + } + } + }, + "assetmgmt_asset": { + "name": "assetmgmt_asset", + "fields": { + "assetmgmt_asset_id": { + "name": "assetmgmt_asset_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "assetmgmt_asset_name": { + "name": "assetmgmt_asset_name", + "type": "VARCHAR(255)", + "null": false + }, + "assetmgmt_asset_number": { + "name": "assetmgmt_asset_number", + "type": "VARCHAR(255)", + "null": false + }, + "assetmgmt_asset_status": { + "name": "assetmgmt_asset_status", + "type": "TINYINT", + "null": false + }, + "assetmgmt_asset_type": { + "name": "assetmgmt_asset_type", + "type": "INT", + "foreignTable": "assetmgmt_asset_type", + "foreignKey": "assetmgmt_asset_type_id" + }, + "assetmgmt_asset_info": { + "name": "assetmgmt_asset_info", + "type": "TEXT", + "null": false + }, + "assetmgmt_asset_created_at": { + "name": "assetmgmt_asset_created_at", + "type": "DATETIME", + "null": false + }, + "assetmgmt_asset_responsible": { + "name": "assetmgmt_asset_responsible", + "type": "INT", + "null": true, + "default": true, + "foreignTable": "account", + "foreignKey": "account_id" + }, + "assetmgmt_asset_unit": { + "name": "assetmgmt_asset_unit", + "type": "INT", + "default": null, + "null": true, + "foreignTable": "unit", + "foreignKey": "unit_id" + } + } + }, + "assetmgmt_attr_type": { + "name": "assetmgmt_attr_type", + "fields": { + "assetmgmt_attr_type_id": { + "name": "assetmgmt_attr_type_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "assetmgmt_attr_type_name": { + "name": "assetmgmt_attr_type_name", + "type": "VARCHAR(255)", + "null": false, + "unique": true + }, + "assetmgmt_attr_type_datatype": { + "name": "assetmgmt_attr_type_datatype", + "type": "INT(11)", + "null": false + }, + "assetmgmt_attr_type_fields": { + "name": "assetmgmt_attr_type_fields", + "type": "INT(11)", + "null": false + }, + "assetmgmt_attr_type_custom": { + "name": "assetmgmt_attr_type_custom", + "type": "TINYINT(1)", + "null": false + }, + "assetmgmt_attr_type_required": { + "description": "Every asset must have this attribute type if set to true.", + "name": "assetmgmt_attr_type_required", + "type": "TINYINT(1)", + "null": false + }, + "assetmgmt_attr_type_pattern": { + "description": "This is a regex validation pattern.", + "name": "assetmgmt_attr_type_pattern", + "type": "VARCHAR(255)", + "null": false + } + } + }, + "assetmgmt_attr_type_l11n": { + "name": "assetmgmt_attr_type_l11n", + "fields": { + "assetmgmt_attr_type_l11n_id": { + "name": "assetmgmt_attr_type_l11n_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "assetmgmt_attr_type_l11n_title": { + "name": "assetmgmt_attr_type_l11n_title", + "type": "VARCHAR(255)", + "null": false + }, + "assetmgmt_attr_type_l11n_type": { + "name": "assetmgmt_attr_type_l11n_type", + "type": "INT(11)", + "null": false, + "foreignTable": "assetmgmt_attr_type", + "foreignKey": "assetmgmt_attr_type_id" + }, + "assetmgmt_attr_type_l11n_lang": { + "name": "assetmgmt_attr_type_l11n_lang", + "type": "VARCHAR(2)", + "null": false, + "foreignTable": "language", + "foreignKey": "language_639_1" + } + } + }, + "assetmgmt_attr_value": { + "name": "assetmgmt_attr_value", + "fields": { + "assetmgmt_attr_value_id": { + "name": "assetmgmt_attr_value_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "assetmgmt_attr_value_default": { + "name": "assetmgmt_attr_value_default", + "type": "TINYINT(1)", + "null": false + }, + "assetmgmt_attr_value_valueStr": { + "name": "assetmgmt_attr_value_valueStr", + "type": "VARCHAR(255)", + "null": true, + "default": null + }, + "assetmgmt_attr_value_valueInt": { + "name": "assetmgmt_attr_value_valueInt", + "type": "INT(11)", + "null": true, + "default": null + }, + "assetmgmt_attr_value_valueDec": { + "name": "assetmgmt_attr_value_valueDec", + "type": "DECIMAL(19,5)", + "null": true, + "default": null + }, + "assetmgmt_attr_value_valueDat": { + "name": "assetmgmt_attr_value_valueDat", + "type": "DATETIME", + "null": true, + "default": null + }, + "assetmgmt_attr_value_unit": { + "name": "assetmgmt_attr_value_unit", + "type": "VARCHAR(255)", + "null": false + }, + "assetmgmt_attr_value_deptype": { + "name": "assetmgmt_attr_value_deptype", + "type": "INT(11)", + "null": true, + "default": null, + "foreignTable": "assetmgmt_attr_type", + "foreignKey": "assetmgmt_attr_type_id" + }, + "assetmgmt_attr_value_depvalue": { + "name": "assetmgmt_attr_value_depvalue", + "type": "INT(11)", + "null": true, + "default": null, + "foreignTable": "assetmgmt_attr_value", + "foreignKey": "assetmgmt_attr_value_id" + } + } + }, + "assetmgmt_attr_value_l11n": { + "name": "assetmgmt_attr_value_l11n", + "fields": { + "assetmgmt_attr_value_l11n_id": { + "name": "assetmgmt_attr_value_l11n_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "assetmgmt_attr_value_l11n_title": { + "name": "assetmgmt_attr_value_l11n_title", + "type": "VARCHAR(255)", + "null": false + }, + "assetmgmt_attr_value_l11n_value": { + "name": "assetmgmt_attr_value_l11n_value", + "type": "INT(11)", + "null": false, + "foreignTable": "assetmgmt_attr_value", + "foreignKey": "assetmgmt_attr_value_id" + }, + "assetmgmt_attr_value_l11n_lang": { + "name": "assetmgmt_attr_value_l11n_lang", + "type": "VARCHAR(2)", + "null": false, + "foreignTable": "language", + "foreignKey": "language_639_1" + } + } + }, + "assetmgmt_asset_attr_default": { + "name": "assetmgmt_asset_attr_default", + "fields": { + "assetmgmt_asset_attr_default_id": { + "name": "assetmgmt_asset_attr_default_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "assetmgmt_asset_attr_default_type": { + "name": "assetmgmt_asset_attr_default_type", + "type": "INT(11)", + "null": false, + "foreignTable": "assetmgmt_attr_type", + "foreignKey": "assetmgmt_attr_type_id" + }, + "assetmgmt_asset_attr_default_value": { + "name": "assetmgmt_asset_attr_default_value", + "type": "INT(11)", + "null": false, + "foreignTable": "assetmgmt_attr_value", + "foreignKey": "assetmgmt_attr_value_id" + } + } + }, + "assetmgmt_asset_attr": { + "name": "assetmgmt_asset_attr", + "fields": { + "assetmgmt_asset_attr_id": { + "name": "assetmgmt_asset_attr_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "assetmgmt_asset_attr_asset": { + "name": "assetmgmt_asset_attr_asset", + "type": "INT(11)", + "null": false, + "foreignTable": "assetmgmt_asset", + "foreignKey": "assetmgmt_asset_id" + }, + "assetmgmt_asset_attr_type": { + "name": "assetmgmt_asset_attr_type", + "type": "INT(11)", + "null": false, + "foreignTable": "assetmgmt_attr_type", + "foreignKey": "assetmgmt_attr_type_id" + }, + "assetmgmt_asset_attr_value": { + "name": "assetmgmt_asset_attr_value", + "type": "INT(11)", + "null": true, + "default": null, + "foreignTable": "assetmgmt_attr_value", + "foreignKey": "assetmgmt_attr_value_id" + } + } + }, + "assetmgmt_asset_media": { + "name": "assetmgmt_asset_media", + "fields": { + "assetmgmt_asset_media_id": { + "name": "assetmgmt_asset_media_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "assetmgmt_asset_media_asset": { + "name": "assetmgmt_asset_media_asset", + "type": "INT", + "null": false, + "foreignTable": "assetmgmt_asset", + "foreignKey": "assetmgmt_asset_id" + }, + "assetmgmt_asset_media_media": { + "name": "assetmgmt_asset_media_media", + "type": "INT", + "null": false, + "foreignTable": "media", + "foreignKey": "media_id" + } + } + }, + "assetmgmt_asset_note": { + "name": "assetmgmt_asset_note", + "fields": { + "assetmgmt_asset_note_id": { + "name": "assetmgmt_asset_note_id", + "type": "INT", + "null": false, + "primary": true, + "autoincrement": true + }, + "assetmgmt_asset_note_asset": { + "name": "assetmgmt_asset_note_asset", + "type": "INT", + "null": false, + "foreignTable": "assetmgmt_asset", + "foreignKey": "assetmgmt_asset_id" + }, + "assetmgmt_asset_note_doc": { + "name": "assetmgmt_asset_note_doc", + "type": "INT", + "null": false, + "foreignTable": "editor_doc", + "foreignKey": "editor_doc_id" + } + } + } +} \ No newline at end of file diff --git a/Admin/Installer.php b/Admin/Installer.php index 455f1d0..c03a9c1 100644 --- a/Admin/Installer.php +++ b/Admin/Installer.php @@ -14,7 +14,13 @@ declare(strict_types=1); namespace Modules\AssetManagement\Admin; +use phpOMS\Application\ApplicationAbstract; +use phpOMS\Config\SettingsInterface; +use phpOMS\Message\Http\HttpRequest; +use phpOMS\Message\Http\HttpResponse; use phpOMS\Module\InstallerAbstract; +use phpOMS\Module\ModuleInfo; +use phpOMS\Uri\HttpUri; /** * Installer class. @@ -33,4 +39,297 @@ final class Installer extends InstallerAbstract * @since 1.0.0 */ public const PATH = __DIR__; + + /** + * {@inheritdoc} + */ + public static function install(ApplicationAbstract $app, ModuleInfo $info, SettingsInterface $cfgHandler) : void + { + parent::install($app, $info, $cfgHandler); + + /* Attributes */ + $fileContent = \file_get_contents(__DIR__ . '/Install/attributes.json'); + if ($fileContent === false) { + return; + } + + /** @var array $attributes */ + $attributes = \json_decode($fileContent, true); + $attrTypes = self::createAttributeTypes($app, $attributes); + $attrValues = self::createAttributeValues($app, $attrTypes, $attributes); + + /* Asset types */ + $fileContent = \file_get_contents(__DIR__ . '/Install/assettype.json'); + if ($fileContent === false) { + return; + } + + /** @var array $types */ + $types = \json_decode($fileContent, true); + $assetTypes = self::createAssetTypes($app, $types); + } + + /** + * Install asset type + * + * @param ApplicationAbstract $app Application + * @param array $types Attribute definition + * + * @return array + * + * @since 1.0.0 + */ + private static function createAssetTypes(ApplicationAbstract $app, array $types) : array + { + /** @var array $assetTypes */ + $assetTypes = []; + + /** @var \Modules\AssetManagement\Controller\ApiAssetTypeController $module */ + $module = $app->moduleManager->getModuleInstance('AssetManagement', 'ApiAssetType'); + + /** @var array $type */ + foreach ($types as $type) { + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('duration', $type['duration']); + $request->setData('industry', $type['industry']); + $request->setData('title', \reset($type['l11n'])); + $request->setData('language', \array_keys($type['l11n'])[0] ?? 'en'); + + $module->apiAssetTypeCreate($request, $response); + + $responseData = $response->getData(''); + if (!\is_array($responseData)) { + continue; + } + + $assetType = \is_array($responseData['response']) + ? $responseData['response'] + : $responseData['response']->toArray(); + + $assetTypes[] = $assetType; + + $isFirst = true; + foreach ($type['l11n'] as $language => $l11n) { + if ($isFirst) { + $isFirst = false; + continue; + } + + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('title', $l11n); + $request->setData('language', $language); + $request->setData('type', $assetType['id']); + + $module->apiAssetTypeL11nCreate($request, $response); + } + } + + return $assetTypes; + } + + /** + * Install inspection type + * + * @param ApplicationAbstract $app Application + * @param array $types Attribute definition + * + * @return array + * + * @since 1.0.0 + */ + private static function createInspectionTypes(ApplicationAbstract $app, array $types) : array + { + /** @var array $inspectionTypes */ + $inspectionTypes = []; + + /** @var \Modules\AssetManagement\Controller\ApiInspectionTypeController $module */ + $module = $app->moduleManager->getModuleInstance('AssetManagement', 'ApiInspectionType'); + + /** @var array $type */ + foreach ($types as $type) { + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('name', $type['name'] ?? ''); + $request->setData('title', \reset($type['l11n'])); + $request->setData('language', \array_keys($type['l11n'])[0] ?? 'en'); + + $module->apiInspectionTypeCreate($request, $response); + + $responseData = $response->getData(''); + if (!\is_array($responseData)) { + continue; + } + + $inspectionTypes[$type['name']] = \is_array($responseData['response']) + ? $responseData['response'] + : $responseData['response']->toArray(); + + $isFirst = true; + foreach ($type['l11n'] as $language => $l11n) { + if ($isFirst) { + $isFirst = false; + continue; + } + + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('title', $l11n); + $request->setData('language', $language); + $request->setData('type', $inspectionTypes[$type['name']]['id']); + + $module->apiInspectionTypeL11nCreate($request, $response); + } + } + + return $inspectionTypes; + } + + /** + * Install default attribute types + * + * @param ApplicationAbstract $app Application + * @param array $attributes Attribute definition + * + * @return array + * + * @since 1.0.0 + */ + private static function createAttributeTypes(ApplicationAbstract $app, array $attributes) : array + { + /** @var array $itemAttrType */ + $itemAttrType = []; + + /** @var \Modules\AssetManagement\Controller\ApiAssetAttributeController $module */ + $module = $app->moduleManager->getModuleInstance('AssetManagement', 'ApiAssetAttribute'); + + /** @var array $attribute */ + foreach ($attributes as $attribute) { + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('name', $attribute['name'] ?? ''); + $request->setData('title', \reset($attribute['l11n'])); + $request->setData('language', \array_keys($attribute['l11n'])[0] ?? 'en'); + $request->setData('is_required', $attribute['is_required'] ?? false); + $request->setData('custom', $attribute['is_custom_allowed'] ?? false); + $request->setData('validation_pattern', $attribute['validation_pattern'] ?? ''); + $request->setData('datatype', (int) $attribute['value_type']); + + $module->apiAssetAttributeTypeCreate($request, $response); + + $responseData = $response->getData(''); + if (!\is_array($responseData)) { + continue; + } + + $itemAttrType[$attribute['name']] = \is_array($responseData['response']) + ? $responseData['response'] + : $responseData['response']->toArray(); + + $isFirst = true; + foreach ($attribute['l11n'] as $language => $l11n) { + if ($isFirst) { + $isFirst = false; + continue; + } + + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('title', $l11n); + $request->setData('language', $language); + $request->setData('type', $itemAttrType[$attribute['name']]['id']); + + $module->apiAssetAttributeTypeL11nCreate($request, $response); + } + } + + return $itemAttrType; + } + + /** + * Create default attribute values for types + * + * @param ApplicationAbstract $app Application + * @param array $itemAttrType Attribute types + * @param array, is_required?:bool, is_custom_allowed?:bool, validation_pattern?:string, value_type?:string, values?:array}> $attributes Attribute definition + * + * @return array + * + * @since 1.0.0 + */ + private static function createAttributeValues(ApplicationAbstract $app, array $itemAttrType, array $attributes) : array + { + /** @var array $itemAttrValue */ + $itemAttrValue = []; + + /** @var \Modules\AssetManagement\Controller\ApiAssetAttributeController $module */ + $module = $app->moduleManager->getModuleInstance('AssetManagement', 'ApiAssetAttribute'); + + foreach ($attributes as $attribute) { + $itemAttrValue[$attribute['name']] = []; + + /** @var array $value */ + foreach ($attribute['values'] as $value) { + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('value', $value['value'] ?? ''); + $request->setData('unit', $value['unit'] ?? ''); + $request->setData('default', true); // always true since all defined values are possible default values + $request->setData('type', $itemAttrType[$attribute['name']]['id']); + + if (isset($value['l11n']) && !empty($value['l11n'])) { + $request->setData('title', \reset($value['l11n'])); + $request->setData('language', \array_keys($value['l11n'])[0] ?? 'en'); + } + + $module->apiAssetAttributeValueCreate($request, $response); + + $responseData = $response->getData(''); + if (!\is_array($responseData)) { + continue; + } + + $attrValue = \is_array($responseData['response']) + ? $responseData['response'] + : $responseData['response']->toArray(); + + $itemAttrValue[$attribute['name']][] = $attrValue; + + $isFirst = true; + foreach (($value['l11n'] ?? []) as $language => $l11n) { + if ($isFirst) { + $isFirst = false; + continue; + } + + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('title', $l11n); + $request->setData('language', $language); + $request->setData('value', $attrValue['id']); + + $module->apiAssetAttributeValueL11nCreate($request, $response); + } + } + } + + return $itemAttrValue; + } } diff --git a/Admin/Routes/Web/Backend.php b/Admin/Routes/Web/Backend.php index 0394b78..66d4c6d 100644 --- a/Admin/Routes/Web/Backend.php +++ b/Admin/Routes/Web/Backend.php @@ -1,11 +1,34 @@ [ + [ + 'dest' => '\Modules\EquipmentManagement\Controller\BackendController:viewEquipmentManagementAttributeTypeList', + 'verb' => RouteVerb::GET, + 'permission' => [ + 'module' => BackendController::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::ASSET, + ], + ], + ], + '^.*/accounting/attribute/type\?.*$' => [ + [ + 'dest' => '\Modules\EquipmentManagement\Controller\BackendController:viewEquipmentManagementAttributeType', + 'verb' => RouteVerb::GET, + 'permission' => [ + 'module' => BackendController::NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::ASSET, + ], + ], + ], + '^.*/accounting/asset/list.*$' => [ [ 'dest' => '\Modules\AssetManagement\Controller\BackendController:viewAssetManagementList', @@ -13,8 +36,63 @@ return [ 'permission' => [ 'module' => BackendController::MODULE_NAME, 'type' => PermissionType::READ, - 'state' => PermissionState::ASSET, + 'state' => PermissionCategory::ASSET, ], ], ], + '^.*/accounting/asset/profile.*$' => [ + [ + 'dest' => '\Modules\AssetManagement\Controller\BackendController:viewAssetManagementProfile', + 'verb' => RouteVerb::GET, + 'permission' => [ + 'module' => BackendController::MODULE_NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::ASSET, + ], + ], + ], + '^.*/accounting/asset/entry/list.*$' => [ + [ + 'dest' => '\Modules\AssetManagement\Controller\BackendController:viewAssetManagementEntryList', + 'verb' => RouteVerb::GET, + 'permission' => [ + 'module' => BackendController::MODULE_NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::ASSET, + ], + ], + ], + '^.*/accounting/asset/entry/view.*$' => [ + [ + 'dest' => '\Modules\AssetManagement\Controller\BackendController:viewAssetManagementEntryView', + 'verb' => RouteVerb::GET, + 'permission' => [ + 'module' => BackendController::MODULE_NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::ASSET, + ], + ], + ], + '^.*/accounting/asset/create.*$' => [ + [ + 'dest' => '\Modules\AssetManagement\Controller\BackendController:viewAssetManagementCreate', + 'verb' => RouteVerb::GET, + 'permission' => [ + 'module' => BackendController::MODULE_NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::ASSET, + ], + ], + ], + '^.*/accounting/asset/table.*$' => [ + [ + 'dest' => '\Modules\AssetManagement\Controller\BackendController:viewAssetManagementAssetTable', + 'verb' => RouteVerb::GET, + 'permission' => [ + 'module' => BackendController::MODULE_NAME, + 'type' => PermissionType::READ, + 'state' => PermissionCategory::ASSET, + ], + ], + ] ]; diff --git a/Controller/ApiAssetAttributeController.php b/Controller/ApiAssetAttributeController.php new file mode 100644 index 0000000..5dfdf71 --- /dev/null +++ b/Controller/ApiAssetAttributeController.php @@ -0,0 +1,524 @@ +validateAttributeCreate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidCreateResponse($request, $response, $val); + + return; + } + + $type = AssetAttributeTypeMapper::get()->with('defaults')->where('id', (int) $request->getData('type'))->execute(); + $attribute = $this->createAttributeFromRequest($request, $type); + $this->createModel($request->header->account, $attribute, AssetAttributeMapper::class, 'attribute', $request->getOrigin()); + $this->createStandardCreateResponse($request, $response, $attribute); + } + + /** + * Api method to create asset attribute l11n + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiAssetAttributeTypeL11nCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeTypeL11nCreate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidCreateResponse($request, $response, $val); + + return; + } + + $attrL11n = $this->createAttributeTypeL11nFromRequest($request); + $this->createModel($request->header->account, $attrL11n, AssetAttributeTypeL11nMapper::class, 'attr_type_l11n', $request->getOrigin()); + $this->createStandardCreateResponse($request, $response, $attrL11n); + } + + /** + * Api method to create asset attribute type + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiAssetAttributeTypeCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeTypeCreate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidCreateResponse($request, $response, $val); + + return; + } + + $attrType = $this->createAttributeTypeFromRequest($request); + $this->createModel($request->header->account, $attrType, AssetAttributeTypeMapper::class, 'attr_type', $request->getOrigin()); + $this->createStandardCreateResponse($request, $response, $attrType); + } + + /** + * Api method to create asset attribute value + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiAssetAttributeValueCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeValueCreate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidCreateResponse($request, $response, $val); + + return; + } + + /** @var \Modules\Attribute\Models\AttributeType $type */ + $type = AssetAttributeTypeMapper::get() + ->where('id', $request->getDataInt('type') ?? 0) + ->execute(); + + $attrValue = $this->createAttributeValueFromRequest($request, $type); + $this->createModel($request->header->account, $attrValue, AssetAttributeValueMapper::class, 'attr_value', $request->getOrigin()); + + if ($attrValue->isDefault) { + $this->createModelRelation( + $request->header->account, + (int) $request->getData('type'), + $attrValue->id, + AssetAttributeTypeMapper::class, 'defaults', '', $request->getOrigin() + ); + } + + $this->createStandardCreateResponse($request, $response, $attrValue); + } + + /** + * Api method to create asset attribute l11n + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiAssetAttributeValueL11nCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeValueL11nCreate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidCreateResponse($request, $response, $val); + + return; + } + + $attrL11n = $this->createAttributeValueL11nFromRequest($request); + $this->createModel($request->header->account, $attrL11n, AssetAttributeValueL11nMapper::class, 'attr_value_l11n', $request->getOrigin()); + $this->createStandardCreateResponse($request, $response, $attrL11n); + } + + /** + * Api method to update AssetAttribute + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiAssetAttributeUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeUpdate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidUpdateResponse($request, $response, $val); + + return; + } + + /** @var Attribute $old */ + $old = AssetAttributeMapper::get() + ->with('type') + ->with('type/defaults') + ->with('value') + ->where('id', (int) $request->getData('id')) + ->execute(); + + $new = $this->updateAttributeFromRequest($request, clone $old); + + if ($new->id === 0) { + // Set response header to invalid request because of invalid data + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidUpdateResponse($request, $response, $new); + + return; + } + + $this->updateModel($request->header->account, $old, $new, AssetAttributeMapper::class, 'asset_attribute', $request->getOrigin()); + + if ($new->value->getValue() !== $old->value->getValue() + && $new->type->custom + ) { + $this->updateModel($request->header->account, $old->value, $new->value, AssetAttributeValueMapper::class, 'attribute_value', $request->getOrigin()); + } + + $this->createStandardUpdateResponse($request, $response, $new); + } + + /** + * Api method to delete AssetAttribute + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiAssetAttributeDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeDelete($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidDeleteResponse($request, $response, $val); + + return; + } + + $assetAttribute = AssetAttributeMapper::get() + ->with('type') + ->where('id', (int) $request->getData('id')) + ->execute(); + + if ($assetAttribute->type->isRequired) { + $this->createInvalidDeleteResponse($request, $response, []); + + return; + } + + $this->deleteModel($request->header->account, $assetAttribute, AssetAttributeMapper::class, 'asset_attribute', $request->getOrigin()); + $this->createStandardDeleteResponse($request, $response, $assetAttribute); + } + + /** + * Api method to update AssetAttributeTypeL11n + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiAssetAttributeTypeL11nUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeTypeL11nUpdate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidUpdateResponse($request, $response, $val); + + return; + } + + /** @var BaseStringL11n $old */ + $old = AssetAttributeTypeL11nMapper::get()->where('id', (int) $request->getData('id'))->execute(); + $new = $this->updateAttributeTypeL11nFromRequest($request, clone $old); + + $this->updateModel($request->header->account, $old, $new, AssetAttributeTypeL11nMapper::class, 'asset_attribute_type_l11n', $request->getOrigin()); + $this->createStandardUpdateResponse($request, $response, $new); + } + + /** + * Api method to delete AssetAttributeTypeL11n + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiAssetAttributeTypeL11nDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeTypeL11nDelete($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidDeleteResponse($request, $response, $val); + + return; + } + + /** @var BaseStringL11n $assetAttributeTypeL11n */ + $assetAttributeTypeL11n = AssetAttributeTypeL11nMapper::get()->where('id', (int) $request->getData('id'))->execute(); + $this->deleteModel($request->header->account, $assetAttributeTypeL11n, AssetAttributeTypeL11nMapper::class, 'asset_attribute_type_l11n', $request->getOrigin()); + $this->createStandardDeleteResponse($request, $response, $assetAttributeTypeL11n); + } + + /** + * Api method to update AssetAttributeType + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiAssetAttributeTypeUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeTypeUpdate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidUpdateResponse($request, $response, $val); + + return; + } + + /** @var AttributeType $old */ + $old = AssetAttributeTypeMapper::get()->with('defaults')->where('id', (int) $request->getData('id'))->execute(); + $new = $this->updateAttributeTypeFromRequest($request, clone $old); + + $this->updateModel($request->header->account, $old, $new, AssetAttributeTypeMapper::class, 'asset_attribute_type', $request->getOrigin()); + $this->createStandardUpdateResponse($request, $response, $new); + } + + /** + * Api method to delete AssetAttributeType + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @todo Implement API function + * + * @since 1.0.0 + */ + public function apiAssetAttributeTypeDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeTypeDelete($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidDeleteResponse($request, $response, $val); + + return; + } + + /** @var AttributeType $assetAttributeType */ + $assetAttributeType = AssetAttributeTypeMapper::get()->with('defaults')->where('id', (int) $request->getData('id'))->execute(); + $this->deleteModel($request->header->account, $assetAttributeType, AssetAttributeTypeMapper::class, 'asset_attribute_type', $request->getOrigin()); + $this->createStandardDeleteResponse($request, $response, $assetAttributeType); + } + + /** + * Api method to update AssetAttributeValue + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiAssetAttributeValueUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeValueUpdate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidUpdateResponse($request, $response, $val); + + return; + } + + /** @var AttributeValue $old */ + $old = AssetAttributeValueMapper::get()->where('id', (int) $request->getData('id'))->execute(); + + /** @var \Modules\Attribute\Models\Attribute $attr */ + $attr = AssetAttributeMapper::get() + ->with('type') + ->where('id', $request->getDataInt('attribute') ?? 0) + ->execute(); + + $new = $this->updateAttributeValueFromRequest($request, clone $old, $attr); + + $this->updateModel($request->header->account, $old, $new, AssetAttributeValueMapper::class, 'asset_attribute_value', $request->getOrigin()); + $this->createStandardUpdateResponse($request, $response, $new); + } + + /** + * Api method to delete AssetAttributeValue + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiAssetAttributeValueDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + // @todo I don't think values can be deleted? Only Attributes + // However, It should be possible to remove UNUSED default values + // either here or other function? + // if (!empty($val = $this->validateAttributeValueDelete($request))) { + // $response->header->status = RequestStatusCode::R_400; + // $this->createInvalidDeleteResponse($request, $response, $val); + + // return; + // } + + // /** @var \Modules\AssetManagement\Models\AssetAttributeValue $assetAttributeValue */ + // $assetAttributeValue = AssetAttributeValueMapper::get()->where('id', (int) $request->getData('id'))->execute(); + // $this->deleteModel($request->header->account, $assetAttributeValue, AssetAttributeValueMapper::class, 'asset_attribute_value', $request->getOrigin()); + // $this->createStandardDeleteResponse($request, $response, $assetAttributeValue); + } + + /** + * Api method to update AssetAttributeValueL11n + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiAssetAttributeValueL11nUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeValueL11nUpdate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidUpdateResponse($request, $response, $val); + + return; + } + + /** @var BaseStringL11n $old */ + $old = AssetAttributeValueL11nMapper::get()->where('id', (int) $request->getData('id')); + $new = $this->updateAttributeValueL11nFromRequest($request, clone $old); + + $this->updateModel($request->header->account, $old, $new, AssetAttributeValueL11nMapper::class, 'asset_attribute_value_l11n', $request->getOrigin()); + $this->createStandardUpdateResponse($request, $response, $new); + } + + /** + * Api method to delete AssetAttributeValueL11n + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiAssetAttributeValueL11nDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAttributeValueL11nDelete($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidDeleteResponse($request, $response, $val); + + return; + } + + /** @var BaseStringL11n $assetAttributeValueL11n */ + $assetAttributeValueL11n = AssetAttributeValueL11nMapper::get()->where('id', (int) $request->getData('id'))->execute(); + $this->deleteModel($request->header->account, $assetAttributeValueL11n, AssetAttributeValueL11nMapper::class, 'asset_attribute_value_l11n', $request->getOrigin()); + $this->createStandardDeleteResponse($request, $response, $assetAttributeValueL11n); + } +} diff --git a/Controller/ApiAssetController.php b/Controller/ApiAssetController.php new file mode 100644 index 0000000..bcf8680 --- /dev/null +++ b/Controller/ApiAssetController.php @@ -0,0 +1,634 @@ +validateAssetCreate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidCreateResponse($request, $response, $val); + + return; + } + + /** @var Asset $asset */ + $asset = $this->createAssetFromRequest($request); + $this->createModel($request->header->account, $asset, AssetMapper::class, 'asset', $request->getOrigin()); + + if (!empty($request->files) + || !empty($request->getDataJson('media')) + ) { + $this->createAssetMedia($asset, $request); + } + + $this->createStandardCreateResponse($request, $response, $asset); + } + + /** + * Method to create asset from request. + * + * @param RequestAbstract $request Request + * + * @return Asset Returns the created asset from the request + * + * @since 1.0.0 + */ + public function createAssetFromRequest(RequestAbstract $request) : Asset + { + $asset = new Asset(); + $asset->name = $request->getDataString('name') ?? ''; + $asset->info = $request->getDataString('info') ?? ''; + $asset->type = new NullBaseStringL11nType((int) ($request->getDataInt('type') ?? 0)); + $asset->status = $request->getDataInt('status') ?? AssetStatus::INACTIVE; + $asset->unit = $request->getDataInt('unit') ?? $this->app->unitId; + + return $asset; + } + + /** + * Create media files for asset + * + * @param Asset $asset Asset + * @param RequestAbstract $request Request incl. media do upload + * + * @return void + * + * @since 1.0.0 + */ + private function createAssetMedia(Asset $asset, RequestAbstract $request) : void + { + $path = $this->createAssetDir($asset); + + if (!empty($uploadedFiles = $request->files)) { + $uploaded = $this->app->moduleManager->get('Media')->uploadFiles( + names: [], + fileNames: [], + files: $uploadedFiles, + account: $request->header->account, + basePath: __DIR__ . '/../../../Modules/Media/Files' . $path, + virtualPath: $path, + pathSettings: PathSettings::FILE_PATH + ); + + $collection = null; + foreach ($uploaded as $media) { + $this->createModelRelation( + $request->header->account, + $asset->id, + $media->id, + AssetMapper::class, + 'files', + '', + $request->getOrigin() + ); + + if ($collection === null) { + /** @var \Modules\Media\Models\Collection $collection */ + $collection = MediaMapper::getParentCollection($path)->limit(1)->execute(); + + if ($collection->id === 0) { + $collection = $this->app->moduleManager->get('Media')->createRecursiveMediaCollection( + $path, + $request->header->account, + __DIR__ . '/../../../Modules/Media/Files' . $path + ); + } + } + + $this->createModelRelation( + $request->header->account, + $collection->id, + $media->id, + CollectionMapper::class, + 'sources', + '', + $request->getOrigin() + ); + } + } + + if (!empty($mediaFiles = $request->getDataJson('media'))) { + $collection = null; + + foreach ($mediaFiles as $file) { + /** @var \Modules\Media\Models\Media $media */ + $media = MediaMapper::get()->where('id', (int) $file)->limit(1)->execute(); + + $this->createModelRelation( + $request->header->account, + $asset->id, + $media->id, + AssetMapper::class, + 'files', + '', + $request->getOrigin() + ); + + $ref = new Reference(); + $ref->name = $media->name; + $ref->source = new NullMedia($media->id); + $ref->createdBy = new NullAccount($request->header->account); + $ref->setVirtualPath($path); + + $this->createModel($request->header->account, $ref, ReferenceMapper::class, 'media_reference', $request->getOrigin()); + + if ($collection === null) { + /** @var \Modules\Media\Models\Collection $collection */ + $collection = MediaMapper::getParentCollection($path)->limit(1)->execute(); + + if ($collection->id === 0) { + $collection = $this->app->moduleManager->get('Media')->createRecursiveMediaCollection( + $path, + $request->header->account, + __DIR__ . '/../../../Modules/Media/Files' . $path + ); + } + } + + $this->createModelRelation( + $request->header->account, + $collection->id, + $ref->id, + CollectionMapper::class, + 'sources', + '', + $request->getOrigin() + ); + } + } + } + + /** + * Validate asset create request + * + * @param RequestAbstract $request Request + * + * @return array Returns the validation array of the request + * + * @since 1.0.0 + */ + private function validateAssetCreate(RequestAbstract $request) : array + { + $val = []; + if (($val['name'] = !$request->hasData('name')) + || ($val['type'] = !$request->hasData('type')) + ) { + return $val; + } + + return []; + } + + /** + * Api method to create a bill + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiMediaAddToAsset(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateMediaAddToAsset($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidAddResponse($request, $response, $val); + + return; + } + + /** @var \Modules\AssetManagement\Models\Asset $asset */ + $asset = AssetMapper::get()->where('id', (int) $request->getData('asset'))->execute(); + $path = $this->createAssetDir($asset); + + $uploaded = []; + if (!empty($uploadedFiles = $request->files)) { + $uploaded = $this->app->moduleManager->get('Media')->uploadFiles( + names: [], + fileNames: [], + files: $uploadedFiles, + account: $request->header->account, + basePath: __DIR__ . '/../../../Modules/Media/Files' . $path, + virtualPath: $path, + pathSettings: PathSettings::FILE_PATH, + hasAccountRelation: false, + readContent: $request->getDataBool('parse_content') ?? false + ); + + $collection = null; + foreach ($uploaded as $media) { + $this->createModelRelation( + $request->header->account, + $asset->id, + $media->id, + AssetMapper::class, + 'files', + '', + $request->getOrigin() + ); + + if ($request->hasData('type')) { + $this->createModelRelation( + $request->header->account, + $media->id, + $request->getDataInt('type'), + MediaMapper::class, + 'types', + '', + $request->getOrigin() + ); + } + + if ($collection === null) { + /** @var \Modules\Media\Models\Collection $collection */ + $collection = MediaMapper::getParentCollection($path)->limit(1)->execute(); + + if ($collection->id === 0) { + $collection = $this->app->moduleManager->get('Media')->createRecursiveMediaCollection( + $path, + $request->header->account, + __DIR__ . '/../../../Modules/Media/Files' . $path, + ); + } + } + + $this->createModelRelation( + $request->header->account, + $collection->id, + $media->id, + CollectionMapper::class, + 'sources', + '', + $request->getOrigin() + ); + } + } + + if (!empty($mediaFiles = $request->getDataJson('media'))) { + foreach ($mediaFiles as $media) { + $this->createModelRelation( + $request->header->account, + $asset->id, + (int) $media, + AssetMapper::class, + 'files', + '', + $request->getOrigin() + ); + } + } + + $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Media', 'Media added to asset.', [ + 'upload' => $uploaded, + 'media' => $mediaFiles, + ]); + } + + /** + * Create media directory path + * + * @param Asset $asset Asset + * + * @return string + * + * @since 1.0.0 + */ + private function createAssetDir(Asset $asset) : string + { + return '/Modules/AssetManagement/Asset/' + . $this->app->unitId . '/' + . $asset->id; + } + + /** + * Method to validate bill creation from request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @since 1.0.0 + */ + private function validateMediaAddToAsset(RequestAbstract $request) : array + { + $val = []; + if (($val['media'] = (!$request->hasData('media') && empty($request->files))) + || ($val['asset'] = !$request->hasData('asset')) + ) { + return $val; + } + + return []; + } + + /** + * Api method to create notes + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiNoteCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateNoteCreate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidCreateResponse($request, $response, $val); + + return; + } + + $request->setData('virtualpath', '/Modules/AssetManagement/Asset/' . $request->getData('id'), true); + $this->app->moduleManager->get('Editor', 'Api')->apiEditorCreate($request, $response, $data); + + if ($response->header->status !== RequestStatusCode::R_200) { + return; + } + + $responseData = $response->getDataArray($request->uri->__toString()); + if (!\is_array($responseData)) { + return; + } + + $model = $responseData['response']; + $this->createModelRelation($request->header->account, (int) $request->getData('id'), $model->id, AssetMapper::class, 'notes', '', $request->getOrigin()); + } + + /** + * Validate item note create request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @since 1.0.0 + */ + private function validateNoteCreate(RequestAbstract $request) : array + { + $val = []; + if (($val['id'] = !$request->hasData('id')) + ) { + return $val; + } + + return []; + } + + /** + * Api method to update Asset + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiAssetFind(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + } + + /** + * Api method to update Asset + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiAssetUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAssetUpdate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidUpdateResponse($request, $response, $val); + + return; + } + + /** @var \Modules\AssetManagement\Models\Asset $old */ + $old = AssetMapper::get()->where('id', (int) $request->getData('id'))->execute(); + $new = $this->updateAssetFromRequest($request, clone $old); + + $this->updateModel($request->header->account, $old, $new, AssetMapper::class, 'asset', $request->getOrigin()); + $this->createStandardUpdateResponse($request, $response, $new); + } + + /** + * Method to update Asset from request. + * + * @param RequestAbstract $request Request + * @param Asset $new Model to modify + * + * @return Asset + * + * @todo Implement API update function + * + * @since 1.0.0 + */ + public function updateAssetFromRequest(RequestAbstract $request, Asset $new) : Asset + { + $new->name = $request->getDataString('name') ?? $new->name; + $new->info = $request->getDataString('info') ?? $new->info; + $new->type = $request->hasData('type') ? new NullBaseStringL11nType((int) ($request->getDataInt('type') ?? 0)) : $new->type; + $new->status = $request->getDataInt('status') ?? $new->status; + $new->unit = $request->getDataInt('unit') ?? $this->app->unitId; + + return $new; + } + + /** + * Validate Asset update request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @todo Implement API validation function + * + * @since 1.0.0 + */ + private function validateAssetUpdate(RequestAbstract $request) : array + { + $val = []; + if (($val['id'] = !$request->hasData('id'))) { + return $val; + } + + return []; + } + + /** + * Api method to delete Asset + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiAssetDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAssetDelete($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidDeleteResponse($request, $response, $val); + + return; + } + + /** @var \Modules\AssetManagement\Models\Asset $asset */ + $asset = AssetMapper::get()->where('id', (int) $request->getData('id'))->execute(); + $this->deleteModel($request->header->account, $asset, AssetMapper::class, 'asset', $request->getOrigin()); + $this->createStandardDeleteResponse($request, $response, $asset); + } + + /** + * Validate Asset delete request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @todo Implement API validation function + * + * @since 1.0.0 + */ + private function validateAssetDelete(RequestAbstract $request) : array + { + $val = []; + if (($val['id'] = !$request->hasData('id'))) { + return $val; + } + + return []; + } + + /** + * Api method to update Note + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiNoteUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + $accountId = $request->header->account; + if (!$this->app->accountManager->get($accountId)->hasPermission( + PermissionType::MODIFY, $this->app->unitId, $this->app->appId, self::NAME, PermissionCategory::ASSET_NOTE, $request->getDataInt('id')) + ) { + $this->fillJsonResponse($request, $response, NotificationLevel::HIDDEN, '', '', []); + $response->header->status = RequestStatusCode::R_403; + + return; + } + + $this->app->moduleManager->get('Editor', 'Api')->apiEditorUpdate($request, $response, $data); + } + + /** + * Api method to delete Note + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiNoteDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + $accountId = $request->header->account; + if (!$this->app->accountManager->get($accountId)->hasPermission( + PermissionType::DELETE, $this->app->unitId, $this->app->appId, self::NAME, PermissionCategory::ASSET_NOTE, $request->getDataInt('id')) + ) { + $this->fillJsonResponse($request, $response, NotificationLevel::HIDDEN, '', '', []); + $response->header->status = RequestStatusCode::R_403; + + return; + } + + $this->app->moduleManager->get('Editor', 'Api')->apiEditorDelete($request, $response, $data); + } +} diff --git a/Controller/ApiAssetTypeController.php b/Controller/ApiAssetTypeController.php new file mode 100644 index 0000000..ddf2229 --- /dev/null +++ b/Controller/ApiAssetTypeController.php @@ -0,0 +1,405 @@ +validateAssetTypeCreate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidCreateResponse($request, $response, $val); + + return; + } + + $assetType = $this->createAssetTypeFromRequest($request); + $this->createModel($request->header->account, $assetType, AssetTypeMapper::class, 'asset_type', $request->getOrigin()); + $this->createStandardCreateResponse($request, $response, $assetType); + } + + /** + * Method to create item attribute from request. + * + * @param RequestAbstract $request Request + * + * @return AssetType + * + * @since 1.0.0 + */ + private function createAssetTypeFromRequest(RequestAbstract $request) : AssetType + { + $assetType = new AssetType(); + $assetType->setL11n($request->getDataString('title') ?? '', $request->getDataString('language') ?? ISO639x1Enum::_EN); + $assetType->depreciationDuration = $request->getDataInt('duration') ?? 0; + $assetType->industry = $request->getDataInt('industry') ?? 0; + + return $assetType; + } + + /** + * Validate item attribute create request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @since 1.0.0 + */ + private function validateAssetTypeCreate(RequestAbstract $request) : array + { + $val = []; + if (($val['title'] = !$request->hasData('title')) + ) { + return $val; + } + + return []; + } + + /** + * Api method to create item attribute l11n + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiAssetTypeL11nCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAssetTypeL11nCreate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidCreateResponse($request, $response, $val); + + return; + } + + $assetTypeL11n = $this->createAssetTypeL11nFromRequest($request); + $this->createModel($request->header->account, $assetTypeL11n, AssetTypeL11nMapper::class, 'asset_type_l11n', $request->getOrigin()); + $this->createStandardCreateResponse($request, $response, $assetTypeL11n); + } + + /** + * Method to create item attribute l11n from request. + * + * @param RequestAbstract $request Request + * + * @return BaseStringL11n + * + * @since 1.0.0 + */ + private function createAssetTypeL11nFromRequest(RequestAbstract $request) : BaseStringL11n + { + $assetTypeL11n = new BaseStringL11n(); + $assetTypeL11n->ref = $request->getDataInt('type') ?? 0; + $assetTypeL11n->setLanguage( + $request->getDataString('language') ?? $request->header->l11n->language + ); + $assetTypeL11n->content = $request->getDataString('title') ?? ''; + + return $assetTypeL11n; + } + + /** + * Validate item attribute l11n create request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @since 1.0.0 + */ + private function validateAssetTypeL11nCreate(RequestAbstract $request) : array + { + $val = []; + if (($val['title'] = !$request->hasData('title')) + || ($val['type'] = !$request->hasData('type')) + ) { + return $val; + } + + return []; + } + + /** + * Api method to update AssetType + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiAssetTypeUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAssetTypeUpdate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidUpdateResponse($request, $response, $val); + + return; + } + + /** @var BaseStringL11nType $old */ + $old = AssetTypeMapper::get()->where('id', (int) $request->getData('id')); + $new = $this->updateAssetTypeFromRequest($request, clone $old); + + $this->updateModel($request->header->account, $old, $new, AssetTypeMapper::class, 'asset_type', $request->getOrigin()); + $this->createStandardUpdateResponse($request, $response, $new); + } + + /** + * Method to update AssetType from request. + * + * @param RequestAbstract $request Request + * @param BaseStringL11nType $new Model to modify + * + * @return BaseStringL11nType + * + * @todo Implement API update function + * + * @since 1.0.0 + */ + public function updateAssetTypeFromRequest(RequestAbstract $request, BaseStringL11nType $new) : BaseStringL11nType + { + $new->title = $request->getDataString('name') ?? $new->title; + + return $new; + } + + /** + * Validate AssetType update request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @todo Implement API validation function + * + * @since 1.0.0 + */ + private function validateAssetTypeUpdate(RequestAbstract $request) : array + { + $val = []; + if (($val['id'] = !$request->hasData('id'))) { + return $val; + } + + return []; + } + + /** + * Api method to delete AssetType + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiAssetTypeDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAssetTypeDelete($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidDeleteResponse($request, $response, $val); + + return; + } + + /** @var BaseStringL11nType $assetType */ + $assetType = AssetTypeMapper::get()->where('id', (int) $request->getData('id'))->execute(); + $this->deleteModel($request->header->account, $assetType, AssetTypeMapper::class, 'asset_type', $request->getOrigin()); + $this->createStandardDeleteResponse($request, $response, $assetType); + } + + /** + * Validate AssetType delete request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @since 1.0.0 + */ + private function validateAssetTypeDelete(RequestAbstract $request) : array + { + $val = []; + if (($val['id'] = !$request->hasData('id'))) { + return $val; + } + + return []; + } + + /** + * Api method to update AssetTypeL11n + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiAssetTypeL11nUpdate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAssetTypeL11nUpdate($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidUpdateResponse($request, $response, $val); + + return; + } + + /** @var BaseStringL11n $old */ + $old = AssetTypeL11nMapper::get()->where('id', (int) $request->getData('id')); + $new = $this->updateAssetTypeL11nFromRequest($request, clone $old); + + $this->updateModel($request->header->account, $old, $new, AssetTypeL11nMapper::class, 'asset_type_l11n', $request->getOrigin()); + $this->createStandardUpdateResponse($request, $response, $new); + } + + /** + * Method to update AssetTypeL11n from request. + * + * @param RequestAbstract $request Request + * @param BaseStringL11n $new Model to modify + * + * @return BaseStringL11n + * + * @since 1.0.0 + */ + public function updateAssetTypeL11nFromRequest(RequestAbstract $request, BaseStringL11n $new) : BaseStringL11n + { + $new->setLanguage( + $request->getDataString('language') ?? $new->language + ); + $new->content = $request->getDataString('title') ?? $new->content; + + return $new; + } + + /** + * Validate AssetTypeL11n update request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @since 1.0.0 + */ + private function validateAssetTypeL11nUpdate(RequestAbstract $request) : array + { + $val = []; + if (($val['id'] = !$request->hasData('id'))) { + return $val; + } + + return []; + } + + /** + * Api method to delete AssetTypeL11n + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return void + * + * @api + * + * @since 1.0.0 + */ + public function apiAssetTypeL11nDelete(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void + { + if (!empty($val = $this->validateAssetTypeL11nDelete($request))) { + $response->header->status = RequestStatusCode::R_400; + $this->createInvalidDeleteResponse($request, $response, $val); + + return; + } + + /** @var BaseStringL11n $assetTypeL11n */ + $assetTypeL11n = AssetTypeL11nMapper::get()->where('id', (int) $request->getData('id'))->execute(); + $this->deleteModel($request->header->account, $assetTypeL11n, AssetTypeL11nMapper::class, 'asset_type_l11n', $request->getOrigin()); + $this->createStandardDeleteResponse($request, $response, $assetTypeL11n); + } + + /** + * Validate AssetTypeL11n delete request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @since 1.0.0 + */ + private function validateAssetTypeL11nDelete(RequestAbstract $request) : array + { + $val = []; + if (($val['id'] = !$request->hasData('id'))) { + return $val; + } + + return []; + } +} diff --git a/Controller/BackendController.php b/Controller/BackendController.php index a8a0aa7..02d525f 100644 --- a/Controller/BackendController.php +++ b/Controller/BackendController.php @@ -14,7 +14,17 @@ declare(strict_types=1); namespace Modules\AssetManagement\Controller; +use Modules\Admin\Models\LocalizationMapper; +use Modules\Admin\Models\SettingsEnum; +use Modules\AssetManagement\Models\AssetMapper; +use Modules\AssetManagement\Models\AssetTypeMapper; +use Modules\AssetManagement\Models\Attribute\AssetAttributeTypeL11nMapper; +use Modules\AssetManagement\Models\Attribute\AssetAttributeTypeMapper; +use Modules\Media\Models\MediaMapper; +use Modules\Media\Models\MediaTypeMapper; +use Modules\Organization\Models\UnitMapper; use phpOMS\Contract\RenderableInterface; +use phpOMS\DataStorage\Database\Query\Builder; use phpOMS\Message\RequestAbstract; use phpOMS\Message\ResponseAbstract; use phpOMS\Views\View; @@ -30,7 +40,7 @@ use phpOMS\Views\View; final class BackendController extends Controller { /** - * Routing end-point for application behaviour. + * Routing end-point for application behavior. * * @param RequestAbstract $request Request * @param ResponseAbstract $response Response @@ -47,6 +57,134 @@ final class BackendController extends Controller $view->setTemplate('/Modules/AssetManagement/Theme/Backend/asset-list'); $view->data['nav'] = $this->app->moduleManager->get('Navigation')->createNavigationMid(1006601001, $request, $response); + $list = AssetMapper::getAll() + ->with('type') + ->with('type/l11n') + ->where('type/l11n/language', $response->header->l11n->language) + ->sort('id', 'DESC') + ->execute(); + + $view->data['assets'] = $list; + + return $view; + } + + /** + * Routing end-point for application behavior. + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return RenderableInterface + * + * @since 1.0.0 + * @codeCoverageIgnore + */ + public function viewAssetManagementAttributeType(RequestAbstract $request, ResponseAbstract $response, $data = null) : RenderableInterface + { + $view = new View($this->app->l11nManager, $request, $response); + $view->setTemplate('/Modules/AssetManagement/Theme/Backend/asset-profile'); + $view->data['nav'] = $this->app->moduleManager->get('Navigation')->createNavigationMid(1006601001, $request, $response); + + /** @var \Modules\Attribute\Models\AttributeType $attribute */ + $attribute = AssetAttributeTypeMapper::get() + ->with('l11n') + ->where('id', (int) $request->getData('id')) + ->where('l11n/language', $response->header->l11n->language) + ->execute(); + + $l11ns = AssetAttributeTypeL11nMapper::getAll() + ->where('ref', $attribute->id) + ->execute(); + + $view->data['attribute'] = $attribute; + $view->data['l11ns'] = $l11ns; + + return $view; + } + + /** + * Routing end-point for application behavior. + * + * @param RequestAbstract $request Request + * @param ResponseAbstract $response Response + * @param array $data Generic data + * + * @return RenderableInterface Returns a renderable object + * + * @since 1.0.0 + * @codeCoverageIgnore + */ + public function viewAssetManagementAssetProfile(RequestAbstract $request, ResponseAbstract $response, array $data = []) : RenderableInterface + { + $view = new View($this->app->l11nManager, $request, $response); + + $view->setTemplate('/Modules/AssetManagement/Theme/Backend/asset-profile'); + $view->data['nav'] = $this->app->moduleManager->get('Navigation')->createNavigationMid(1008402001, $request, $response); + + // @todo This langauge filtering doesn't work. But it was working with the old mappers. Maybe there is a bug in the where() definition. Need to inspect the actual query. + $asset = AssetMapper::get() + ->with('attributes') + ->with('attributes/type') + ->with('attributes/value') + ->with('attributes/type/l11n') + ->with('files') + ->with('files/types') + ->with('type') + ->with('type/l11n') + ->where('id', (int) $request->getData('id')) + ->where('type/l11n/language', $response->header->l11n->language) + ->where('attributes/type/l11n/language', $response->header->l11n->language) + ->execute(); + + $view->data['asset'] = $asset; + + $query = new Builder($this->app->dbPool->get()); + $results = $query->selectAs(AssetMapper::HAS_MANY['files']['external'], 'file') + ->from(AssetMapper::TABLE) + ->leftJoin(AssetMapper::HAS_MANY['files']['table']) + ->on(AssetMapper::HAS_MANY['files']['table'] . '.' . AssetMapper::HAS_MANY['files']['self'], '=', AssetMapper::TABLE . '.' . AssetMapper::PRIMARYFIELD) + ->leftJoin(MediaMapper::TABLE) + ->on(AssetMapper::HAS_MANY['files']['table'] . '.' . AssetMapper::HAS_MANY['files']['external'], '=', MediaMapper::TABLE . '.' . MediaMapper::PRIMARYFIELD) + ->leftJoin(MediaMapper::HAS_MANY['types']['table']) + ->on(MediaMapper::TABLE . '.' . MediaMapper::PRIMARYFIELD, '=', MediaMapper::HAS_MANY['types']['table'] . '.' . MediaMapper::HAS_MANY['types']['self']) + ->leftJoin(MediaTypeMapper::TABLE) + ->on(MediaMapper::HAS_MANY['types']['table'] . '.' . MediaMapper::HAS_MANY['types']['external'], '=', MediaTypeMapper::TABLE . '.' . MediaTypeMapper::PRIMARYFIELD) + ->where(AssetMapper::HAS_MANY['files']['self'], '=', $asset->id) + ->where(MediaTypeMapper::TABLE . '.' . MediaTypeMapper::getColumnByMember('name'), '=', 'asset_profile_image'); + + $assetImage = MediaMapper::get() + ->with('types') + ->where('id', $results) + ->limit(1) + ->execute(); + + $view->data['assetImage'] = $assetImage; + + $assetTypes = AssetTypeMapper::getAll() + ->with('l11n') + ->where('l11n/language', $response->header->l11n->language) + ->execute(); + + $view->data['types'] = $assetTypes; + + $units = UnitMapper::getAll() + ->execute(); + + $view->data['units'] = $units; + + /** @var \Model\Setting $settings */ + $settings = $this->app->appSettings->get(null, [ + SettingsEnum::DEFAULT_LOCALIZATION, + ]); + + $view->data['attributeView'] = new \Modules\Attribute\Theme\Backend\Components\AttributeView($this->app->l11nManager, $request, $response); + $view->data['attributeView']->data['defaultlocalization'] = LocalizationMapper::get()->where('id', (int) $settings->id)->execute(); + + $view->data['media-upload'] = new \Modules\Media\Theme\Backend\Components\Upload\BaseView($this->app->l11nManager, $request, $response); + $view->data['asset-notes'] = new \Modules\Editor\Theme\Backend\Components\Compound\BaseView($this->app->l11nManager, $request, $response); + return $view; } } diff --git a/Docs/Dev/en/SUMMARY.md b/Docs/Dev/en/SUMMARY.md new file mode 100644 index 0000000..8a97952 --- /dev/null +++ b/Docs/Dev/en/SUMMARY.md @@ -0,0 +1,3 @@ +# Developer Content + +* [Structure]({%}&page=Dev/structure) diff --git a/Docs/Dev/en/structure.md b/Docs/Dev/en/structure.md new file mode 100644 index 0000000..8d70862 --- /dev/null +++ b/Docs/Dev/en/structure.md @@ -0,0 +1,5 @@ +# Structure + +## ER + +![ER](Modules/AssetManagement/Docs/Dev/img/er.png) \ No newline at end of file diff --git a/Docs/Dev/img/er.png b/Docs/Dev/img/er.png new file mode 100644 index 0000000..95dff17 Binary files /dev/null and b/Docs/Dev/img/er.png differ diff --git a/Models/Asset.php b/Models/Asset.php new file mode 100644 index 0000000..b3811ff --- /dev/null +++ b/Models/Asset.php @@ -0,0 +1,79 @@ +createdAt = new \DateTimeImmutable('now'); + $this->type = new BaseStringL11nType(); + } + + /** + * {@inheritdoc} + */ + public function toArray() : array + { + return [ + 'id' => $this->id, + ]; + } + + /** + * {@inheritdoc} + */ + public function jsonSerialize() : mixed + { + return $this->toArray(); + } + + use \Modules\Media\Models\MediaListTrait; + use \Modules\Editor\Models\EditorDocListTrait; + use \Modules\Attribute\Models\AttributeHolderTrait; +} diff --git a/Models/AssetMapper.php b/Models/AssetMapper.php new file mode 100644 index 0000000..bb3f8cf --- /dev/null +++ b/Models/AssetMapper.php @@ -0,0 +1,116 @@ + + */ +final class AssetMapper extends DataMapperFactory +{ + /** + * Columns. + * + * @var array + * @since 1.0.0 + */ + public const COLUMNS = [ + 'assetmgmt_asset_id' => ['name' => 'assetmgmt_asset_id', 'type' => 'int', 'internal' => 'id'], + 'assetmgmt_asset_name' => ['name' => 'assetmgmt_asset_name', 'type' => 'string', 'internal' => 'name'], + 'assetmgmt_asset_number' => ['name' => 'assetmgmt_asset_number', 'type' => 'string', 'internal' => 'number'], + 'assetmgmt_asset_status' => ['name' => 'assetmgmt_asset_status', 'type' => 'int', 'internal' => 'status'], + 'assetmgmt_asset_info' => ['name' => 'assetmgmt_asset_info', 'type' => 'string', 'internal' => 'info'], + 'assetmgmt_asset_unit' => ['name' => 'assetmgmt_asset_unit', 'type' => 'int', 'internal' => 'unit'], + 'assetmgmt_asset_type' => ['name' => 'assetmgmt_asset_type', 'type' => 'int', 'internal' => 'type'], + 'assetmgmt_asset_responsible' => ['name' => 'assetmgmt_asset_responsible', 'type' => 'int', 'internal' => 'responsible'], + 'assetmgmt_asset_created_at' => ['name' => 'assetmgmt_asset_created_at', 'type' => 'DateTimeImmutable', 'internal' => 'createdAt', 'readonly' => true], + ]; + + /** + * Has many relation. + * + * @var array + * @since 1.0.0 + */ + public const HAS_MANY = [ + 'files' => [ + 'mapper' => MediaMapper::class, + 'table' => 'assetmgmt_asset_media', + 'external' => 'assetmgmt_asset_media_media', + 'self' => 'assetmgmt_asset_media_asset', + ], + 'attributes' => [ + 'mapper' => AssetAttributeMapper::class, + 'table' => 'assetmgmt_asset_attr', + 'self' => 'assetmgmt_asset_attr_asset', + 'external' => null, + ], + 'notes' => [ + 'mapper' => EditorDocMapper::class, /* mapper of the related object */ + 'table' => 'assetmgmt_asset_note', /* table of the related object, null if no relation table is used (many->1) */ + 'external' => 'assetmgmt_asset_note_doc', + 'self' => 'assetmgmt_asset_note_asset', + ], + ]; + + /** + * Has one relation. + * + * @var array + * @since 1.0.0 + */ + public const OWNS_ONE = [ + 'type' => [ + 'mapper' => AssetTypeMapper::class, + 'external' => 'assetmgmt_asset_type', + ], + ]; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + public const TABLE = 'assetmgmt_asset'; + + /** + * Created at. + * + * @var string + * @since 1.0.0 + */ + public const CREATED_AT = 'assetmgmt_asset_created_at'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + public const PRIMARYFIELD = 'assetmgmt_asset_id'; +} diff --git a/Models/AssetStatus.php b/Models/AssetStatus.php new file mode 100644 index 0000000..dc208b8 --- /dev/null +++ b/Models/AssetStatus.php @@ -0,0 +1,38 @@ + + */ +final class AssetTypeL11nMapper extends DataMapperFactory +{ + /** + * Columns. + * + * @var array + * @since 1.0.0 + */ + public const COLUMNS = [ + 'assetmgmt_asset_type_l11n_id' => ['name' => 'assetmgmt_asset_type_l11n_id', 'type' => 'int', 'internal' => 'id'], + 'assetmgmt_asset_type_l11n_title' => ['name' => 'assetmgmt_asset_type_l11n_title', 'type' => 'string', 'internal' => 'content', 'autocomplete' => true], + 'assetmgmt_asset_type_l11n_type' => ['name' => 'assetmgmt_asset_type_l11n_type', 'type' => 'int', 'internal' => 'ref'], + 'assetmgmt_asset_type_l11n_lang' => ['name' => 'assetmgmt_asset_type_l11n_lang', 'type' => 'string', 'internal' => 'language'], + ]; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + public const TABLE = 'assetmgmt_asset_type_l11n'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + public const PRIMARYFIELD = 'assetmgmt_asset_type_l11n_id'; + + /** + * Model to use by the mapper. + * + * @var class-string + * @since 1.0.0 + */ + public const MODEL = BaseStringL11n::class; +} diff --git a/Models/AssetTypeMapper.php b/Models/AssetTypeMapper.php new file mode 100644 index 0000000..9c6eb17 --- /dev/null +++ b/Models/AssetTypeMapper.php @@ -0,0 +1,84 @@ + + */ +final class AssetTypeMapper extends DataMapperFactory +{ + /** + * Columns. + * + * @var array + * @since 1.0.0 + */ + public const COLUMNS = [ + 'assetmgmt_asset_type_id' => ['name' => 'assetmgmt_asset_type_id', 'type' => 'int', 'internal' => 'id'], + 'assetmgmt_asset_type_name' => ['name' => 'assetmgmt_asset_type_name', 'type' => 'string', 'internal' => 'title', 'autocomplete' => true], + 'assetmgmt_asset_type_depreciation_duration' => ['name' => 'assetmgmt_asset_type_depreciation_duration', 'type' => 'int', 'internal' => 'depreciationDuration'], + 'assetmgmt_asset_type_industry' => ['name' => 'assetmgmt_asset_type_industry', 'type' => 'int', 'internal' => 'industry'], + + ]; + + /** + * Has many relation. + * + * @var array + * @since 1.0.0 + */ + public const HAS_MANY = [ + 'l11n' => [ + 'mapper' => AssetTypeL11nMapper::class, + 'table' => 'assetmgmt_asset_type_l11n', + 'self' => 'assetmgmt_asset_type_l11n_type', + 'column' => 'content', + 'external' => null, + ], + ]; + + /** + * Model to use by the mapper. + * + * @var class-string + * @since 1.0.0 + */ + public const MODEL = AssetType::class; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + public const TABLE = 'assetmgmt_asset_type'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + public const PRIMARYFIELD = 'assetmgmt_asset_type_id'; +} diff --git a/Models/Attribute/AssetAttributeMapper.php b/Models/Attribute/AssetAttributeMapper.php new file mode 100644 index 0000000..59ff448 --- /dev/null +++ b/Models/Attribute/AssetAttributeMapper.php @@ -0,0 +1,86 @@ + + */ +final class AssetAttributeMapper extends DataMapperFactory +{ + /** + * Columns. + * + * @var array + * @since 1.0.0 + */ + public const COLUMNS = [ + 'assetmgmt_asset_attr_id' => ['name' => 'assetmgmt_asset_attr_id', 'type' => 'int', 'internal' => 'id'], + 'assetmgmt_asset_attr_asset' => ['name' => 'assetmgmt_asset_attr_asset', 'type' => 'int', 'internal' => 'ref'], + 'assetmgmt_asset_attr_type' => ['name' => 'assetmgmt_asset_attr_type', 'type' => 'int', 'internal' => 'type'], + 'assetmgmt_asset_attr_value' => ['name' => 'assetmgmt_asset_attr_value', 'type' => 'int', 'internal' => 'value'], + ]; + + /** + * Has one relation. + * + * @var array + * @since 1.0.0 + */ + public const OWNS_ONE = [ + 'type' => [ + 'mapper' => AssetAttributeTypeMapper::class, + 'external' => 'assetmgmt_asset_attr_type', + ], + 'value' => [ + 'mapper' => AssetAttributeValueMapper::class, + 'external' => 'assetmgmt_asset_attr_value', + ], + ]; + + /** + * Model to use by the mapper. + * + * @var class-string + * @since 1.0.0 + */ + public const MODEL = Attribute::class; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + public const TABLE = 'assetmgmt_asset_attr'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + public const PRIMARYFIELD = 'assetmgmt_asset_attr_id'; +} diff --git a/Models/Attribute/AssetAttributeTypeL11nMapper.php b/Models/Attribute/AssetAttributeTypeL11nMapper.php new file mode 100644 index 0000000..4909e4e --- /dev/null +++ b/Models/Attribute/AssetAttributeTypeL11nMapper.php @@ -0,0 +1,69 @@ + + */ +final class AssetAttributeTypeL11nMapper extends DataMapperFactory +{ + /** + * Columns. + * + * @var array + * @since 1.0.0 + */ + public const COLUMNS = [ + 'assetmgmt_attr_type_l11n_id' => ['name' => 'assetmgmt_attr_type_l11n_id', 'type' => 'int', 'internal' => 'id'], + 'assetmgmt_attr_type_l11n_title' => ['name' => 'assetmgmt_attr_type_l11n_title', 'type' => 'string', 'internal' => 'content', 'autocomplete' => true], + 'assetmgmt_attr_type_l11n_type' => ['name' => 'assetmgmt_attr_type_l11n_type', 'type' => 'int', 'internal' => 'ref'], + 'assetmgmt_attr_type_l11n_lang' => ['name' => 'assetmgmt_attr_type_l11n_lang', 'type' => 'string', 'internal' => 'language'], + ]; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + public const TABLE = 'assetmgmt_attr_type_l11n'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + public const PRIMARYFIELD = 'assetmgmt_attr_type_l11n_id'; + + /** + * Model to use by the mapper. + * + * @var class-string + * @since 1.0.0 + */ + public const MODEL = BaseStringL11n::class; +} diff --git a/Models/Attribute/AssetAttributeTypeMapper.php b/Models/Attribute/AssetAttributeTypeMapper.php new file mode 100644 index 0000000..6ec6937 --- /dev/null +++ b/Models/Attribute/AssetAttributeTypeMapper.php @@ -0,0 +1,94 @@ + + */ +final class AssetAttributeTypeMapper extends DataMapperFactory +{ + /** + * Columns. + * + * @var array + * @since 1.0.0 + */ + public const COLUMNS = [ + 'assetmgmt_attr_type_id' => ['name' => 'assetmgmt_attr_type_id', 'type' => 'int', 'internal' => 'id'], + 'assetmgmt_attr_type_name' => ['name' => 'assetmgmt_attr_type_name', 'type' => 'string', 'internal' => 'name', 'autocomplete' => true], + 'assetmgmt_attr_type_datatype' => ['name' => 'assetmgmt_attr_type_datatype', 'type' => 'int', 'internal' => 'datatype'], + 'assetmgmt_attr_type_fields' => ['name' => 'assetmgmt_attr_type_fields', 'type' => 'int', 'internal' => 'fields'], + 'assetmgmt_attr_type_custom' => ['name' => 'assetmgmt_attr_type_custom', 'type' => 'bool', 'internal' => 'custom'], + 'assetmgmt_attr_type_pattern' => ['name' => 'assetmgmt_attr_type_pattern', 'type' => 'string', 'internal' => 'validationPattern'], + 'assetmgmt_attr_type_required' => ['name' => 'assetmgmt_attr_type_required', 'type' => 'bool', 'internal' => 'isRequired'], + ]; + + /** + * Has many relation. + * + * @var array + * @since 1.0.0 + */ + public const HAS_MANY = [ + 'l11n' => [ + 'mapper' => AssetAttributeTypeL11nMapper::class, + 'table' => 'assetmgmt_attr_type_l11n', + 'self' => 'assetmgmt_attr_type_l11n_type', + 'column' => 'content', + 'external' => null, + ], + 'defaults' => [ + 'mapper' => AssetAttributeValueMapper::class, + 'table' => 'assetmgmt_asset_attr_default', + 'self' => 'assetmgmt_asset_attr_default_type', + 'external' => 'assetmgmt_asset_attr_default_value', + ], + ]; + + /** + * Model to use by the mapper. + * + * @var class-string + * @since 1.0.0 + */ + public const MODEL = AttributeType::class; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + public const TABLE = 'assetmgmt_attr_type'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + public const PRIMARYFIELD = 'assetmgmt_attr_type_id'; +} diff --git a/Models/Attribute/AssetAttributeValueL11nMapper.php b/Models/Attribute/AssetAttributeValueL11nMapper.php new file mode 100644 index 0000000..716ce41 --- /dev/null +++ b/Models/Attribute/AssetAttributeValueL11nMapper.php @@ -0,0 +1,69 @@ + + */ +final class AssetAttributeValueL11nMapper extends DataMapperFactory +{ + /** + * Columns. + * + * @var array + * @since 1.0.0 + */ + public const COLUMNS = [ + 'assetmgmt_attr_value_l11n_id' => ['name' => 'assetmgmt_attr_value_l11n_id', 'type' => 'int', 'internal' => 'id'], + 'assetmgmt_attr_value_l11n_title' => ['name' => 'assetmgmt_attr_value_l11n_title', 'type' => 'string', 'internal' => 'content', 'autocomplete' => true], + 'assetmgmt_attr_value_l11n_value' => ['name' => 'assetmgmt_attr_value_l11n_value', 'type' => 'int', 'internal' => 'ref'], + 'assetmgmt_attr_value_l11n_lang' => ['name' => 'assetmgmt_attr_value_l11n_lang', 'type' => 'string', 'internal' => 'language'], + ]; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + public const TABLE = 'assetmgmt_attr_value_l11n'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + public const PRIMARYFIELD = 'assetmgmt_attr_value_l11n_id'; + + /** + * Model to use by the mapper. + * + * @var class-string + * @since 1.0.0 + */ + public const MODEL = BaseStringL11n::class; +} diff --git a/Models/Attribute/AssetAttributeValueMapper.php b/Models/Attribute/AssetAttributeValueMapper.php new file mode 100644 index 0000000..cbc16b4 --- /dev/null +++ b/Models/Attribute/AssetAttributeValueMapper.php @@ -0,0 +1,89 @@ + + */ +final class AssetAttributeValueMapper extends DataMapperFactory +{ + /** + * Columns. + * + * @var array + * @since 1.0.0 + */ + public const COLUMNS = [ + 'assetmgmt_attr_value_id' => ['name' => 'assetmgmt_attr_value_id', 'type' => 'int', 'internal' => 'id'], + 'assetmgmt_attr_value_default' => ['name' => 'assetmgmt_attr_value_default', 'type' => 'bool', 'internal' => 'isDefault'], + 'assetmgmt_attr_value_valueStr' => ['name' => 'assetmgmt_attr_value_valueStr', 'type' => 'string', 'internal' => 'valueStr'], + 'assetmgmt_attr_value_valueInt' => ['name' => 'assetmgmt_attr_value_valueInt', 'type' => 'int', 'internal' => 'valueInt'], + 'assetmgmt_attr_value_valueDec' => ['name' => 'assetmgmt_attr_value_valueDec', 'type' => 'float', 'internal' => 'valueDec'], + 'assetmgmt_attr_value_valueDat' => ['name' => 'assetmgmt_attr_value_valueDat', 'type' => 'DateTime', 'internal' => 'valueDat'], + 'assetmgmt_attr_value_unit' => ['name' => 'assetmgmt_attr_value_unit', 'type' => 'string', 'internal' => 'unit'], + 'assetmgmt_attr_value_deptype' => ['name' => 'assetmgmt_attr_value_deptype', 'type' => 'int', 'internal' => 'dependingAttributeType'], + 'assetmgmt_attr_value_depvalue' => ['name' => 'assetmgmt_attr_value_depvalue', 'type' => 'int', 'internal' => 'dependingAttributeValue'], + ]; + + /** + * Has many relation. + * + * @var array + * @since 1.0.0 + */ + public const HAS_MANY = [ + 'l11n' => [ + 'mapper' => AssetAttributeValueL11nMapper::class, + 'table' => 'assetmgmt_attr_value_l11n', + 'self' => 'assetmgmt_attr_value_l11n_value', + 'external' => null, + ], + ]; + + /** + * Model to use by the mapper. + * + * @var class-string + * @since 1.0.0 + */ + public const MODEL = AttributeValue::class; + + /** + * Primary table. + * + * @var string + * @since 1.0.0 + */ + public const TABLE = 'assetmgmt_attr_value'; + + /** + * Primary field name. + * + * @var string + * @since 1.0.0 + */ + public const PRIMARYFIELD = 'assetmgmt_attr_value_id'; +} diff --git a/Models/NullAsset.php b/Models/NullAsset.php new file mode 100644 index 0000000..53585d2 --- /dev/null +++ b/Models/NullAsset.php @@ -0,0 +1,47 @@ +id = $id; + parent::__construct(); + } + + /** + * {@inheritdoc} + */ + public function jsonSerialize() : mixed + { + return ['id' => $this->id]; + } +} diff --git a/Models/NullAssetType.php b/Models/NullAssetType.php new file mode 100644 index 0000000..d327bbe --- /dev/null +++ b/Models/NullAssetType.php @@ -0,0 +1,47 @@ +id = $id; + parent::__construct(); + } + + /** + * {@inheritdoc} + */ + public function jsonSerialize() : mixed + { + return ['id' => $this->id]; + } +} diff --git a/Models/PermissionState.php b/Models/PermissionCategory.php similarity index 71% rename from Models/PermissionState.php rename to Models/PermissionCategory.php index c8398f4..1bf6460 100644 --- a/Models/PermissionState.php +++ b/Models/PermissionCategory.php @@ -17,14 +17,20 @@ namespace Modules\AssetManagement\Models; use phpOMS\Stdlib\Base\Enum; /** - * Permision state enum. + * Permission category enum. * * @package Modules\AssetManagement\Models * @license OMS License 2.0 * @link https://jingga.app * @since 1.0.0 */ -abstract class PermissionState extends Enum +abstract class PermissionCategory extends Enum { public const ASSET = 1; + + public const ASSET_TYPE = 3; + + public const ASSET_ATTRIBUTE_TYPE = 6; + + public const ASSET_NOTE = 7; } diff --git a/Theme/Backend/Lang/Navigation.de.lang.php b/Theme/Backend/Lang/Navigation.de.lang.php index 2342b6a..7a75e4e 100644 --- a/Theme/Backend/Lang/Navigation.de.lang.php +++ b/Theme/Backend/Lang/Navigation.de.lang.php @@ -15,4 +15,5 @@ declare(strict_types=1); return ['Navigation' => [ 'Assets' => 'Anlagegüter', 'Dashboard' => 'Dashboard', + 'Table' => 'Tabelle', ]]; diff --git a/Theme/Backend/Lang/Navigation.en.lang.php b/Theme/Backend/Lang/Navigation.en.lang.php index 9d7d007..f9421b9 100644 --- a/Theme/Backend/Lang/Navigation.en.lang.php +++ b/Theme/Backend/Lang/Navigation.en.lang.php @@ -15,4 +15,5 @@ declare(strict_types=1); return ['Navigation' => [ 'Assets' => 'Assets', 'Dashboard' => 'Dashboard', + 'Table' => 'Table', ]]; diff --git a/Theme/Backend/Lang/en.lang.php b/Theme/Backend/Lang/en.lang.php index 80931e5..f80f250 100644 --- a/Theme/Backend/Lang/en.lang.php +++ b/Theme/Backend/Lang/en.lang.php @@ -13,4 +13,13 @@ declare(strict_types=1); return ['AssetManagement' => [ + 'Assets' => 'Assets', + 'Status' => 'Status', + 'Name' => 'Name', + 'Number' => 'Number', + 'Type' => 'Type', + ':status1' => 'Active', + ':status2' => 'Inactive', + ':status3' => 'Damaged', + ':status4' => 'Out of order', ]]; diff --git a/Theme/Backend/asset-list.tpl.php b/Theme/Backend/asset-list.tpl.php index 8896e4f..7b4b40f 100644 --- a/Theme/Backend/asset-list.tpl.php +++ b/Theme/Backend/asset-list.tpl.php @@ -1,4 +1,5 @@ data['nav']->render(); +use phpOMS\Uri\UriFactory; + +/** @var \phpOMS\Views\View $this */ +$assets = $this->data['assets'] ?? []; + +echo $this->data['nav']->render(); ?> +
+
+
+
getHtml('Assets'); ?>download
+
+ + + + + $value) : + ++$count; + $url = UriFactory::build('{/base}/accounting/asset/profile?{?}&id=' . $value->id); + ?> + +
+ getHtml('ID', '0', '0'); ?> + + + + getHtml('Status'); ?> + + + + getHtml('Name'); ?> + + + + getHtml('Type'); ?> + + + +
+ printHtml((string) $value->id); ?> + getHtml(':status' . $value->status); ?> + printHtml($value->name); ?> + printHtml($value->type->getL11n()); ?> + + +
getHtml('Empty', '0', '0'); ?> + +
+
+
+
+
diff --git a/Theme/Backend/asset-profile.tpl.php b/Theme/Backend/asset-profile.tpl.php new file mode 100644 index 0000000..8b6e34c --- /dev/null +++ b/Theme/Backend/asset-profile.tpl.php @@ -0,0 +1,227 @@ +data['asset'] ?? new NullAsset(); +$files = $asset->files; +$assetImage = $this->data['assetImage'] ?? new NullMedia(); +$assetTypes = $this->data['types'] ?? []; +$attributeView = $this->data['attributeView']; + +/** + * @var \phpOMS\Views\View $this + */ +echo $this->data['nav']->render(); +?> +
+
+ +
+
+ request->uri->fragment === 'c-tab-1' ? ' checked' : ''; ?>> +
+
+
+
+
getHtml('Profile'); ?>
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ id === 0) : ?> + + + + +
+
+
+ +
+
+
+ +
+
+
+
+
+ + request->uri->fragment === 'c-tab-2' ? ' checked' : ''; ?>> +
+
+ render( + $asset->attributes, + $this->data['attributeTypes'] ?? [], + $this->data['units'] ?? [], + '{/api}fleet/asset/attribute', + $asset->id + ); + ?> +
+
+ + request->uri->fragment === 'c-tab-3' ? ' checked' : ''; ?>> +
+ data['media-upload']->render('asset-file', 'files', '', $asset->files); ?> +
+ + request->uri->fragment === 'c-tab-4' ? ' checked' : ''; ?>> +
+ data['asset-notes']->render('asset-notes', '', $asset->notes); ?> +
+ + request->uri->fragment === 'c-tab-5' ? ' checked' : ''; ?>> +
+ +
+
+
+
getHtml('Upcoming'); ?>
+ + + + + data['inspections'] as $inspection) : + // @todo handle old inspections in the past? maybe use a status?! + if ($inspection->next === null) { + continue; + } + ?> + +
getHtml('Date'); ?> + getHtml('Type'); ?> + getHtml('Responsible'); ?> +
next->format('Y-m-d H:i'); ?> + printHtml($inspection->type->getL11n()); ?> + + +
+
+
+ +
+
+
getHtml('History'); ?>
+ + + + + data['inspections'] as $inspection) : ?> + +
getHtml('Date'); ?> + getHtml('Type'); ?> + getHtml('Responsible'); ?> +
date->format('Y-m-d H:i'); ?> + printHtml($inspection->type->getL11n()); ?> + + +
+
+
+
+
+ + request->uri->fragment === 'c-tab-8' ? ' checked' : ''; ?>> +
+
+
+
+
+
+
+
\ No newline at end of file diff --git a/Theme/Backend/attribute-type-list.tpl.php b/Theme/Backend/attribute-type-list.tpl.php new file mode 100644 index 0000000..51a227b --- /dev/null +++ b/Theme/Backend/attribute-type-list.tpl.php @@ -0,0 +1,71 @@ +data['attributes']; + +echo $this->data['nav']->render(); ?> + +
+
+
+
getHtml('AttributeTypes', 'Attribute', 'Backend'); ?>download
+
+ + + + + $value) : ++$count; + $url = UriFactory::build('{/base}/accounting/asset/attribute/type?{?}&id=' . $value->id); + ?> + +
getHtml('ID', '0', '0'); ?> + + + + getHtml('Name'); ?> + + + +
id; ?> + printHtml($value->getL11n()); ?> + + +
getHtml('Empty', '0', '0'); ?> + +
+
+
+
+
diff --git a/info.json b/info.json index a446007..2a8802e 100644 --- a/info.json +++ b/info.json @@ -14,17 +14,18 @@ "name": "Jingga", "website": "jingga.app" }, - "description": "Budget Management module.", "directory": "AssetManagement", "dependencies": { "Admin": "*", "Media": "*", "Finance": "*", "Controlling": "*", - "EquipmentManagement": "*" + "EquipmentManagement": "*", + "Editor": "1.0.0" }, "providing": { - "Navigation": "*" + "Navigation": "*", + "Media": "*" }, "load": [ {