{"id":20638470,"url":"https://github.com/ahmetfurkandemir/trendyol-data-engineering-technical-case-study","last_synced_at":"2025-08-15T23:14:20.169Z","repository":{"id":211858451,"uuid":"730092836","full_name":"AhmetFurkanDEMIR/Trendyol-Data-Engineering-Technical-Case-Study","owner":"AhmetFurkanDEMIR","description":"Trendyol Data Engineering Technical Case Study.","archived":false,"fork":false,"pushed_at":"2023-12-11T07:35:24.000Z","size":19973,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-12T06:54:31.951Z","etag":null,"topics":["apache-spark","case-study","data-engineering","debian","docker","maven","scala","spark","trendyol","trendyoltech","ubuntu"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AhmetFurkanDEMIR.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-12-11T07:31:53.000Z","updated_at":"2025-01-20T19:19:22.000Z","dependencies_parsed_at":"2023-12-11T09:48:05.084Z","dependency_job_id":null,"html_url":"https://github.com/AhmetFurkanDEMIR/Trendyol-Data-Engineering-Technical-Case-Study","commit_stats":null,"previous_names":["ahmetfurkandemir/trendyol-data-engineering-technical-case-study"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/AhmetFurkanDEMIR/Trendyol-Data-Engineering-Technical-Case-Study","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AhmetFurkanDEMIR%2FTrendyol-Data-Engineering-Technical-Case-Study","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AhmetFurkanDEMIR%2FTrendyol-Data-Engineering-Technical-Case-Study/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AhmetFurkanDEMIR%2FTrendyol-Data-Engineering-Technical-Case-Study/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AhmetFurkanDEMIR%2FTrendyol-Data-Engineering-Technical-Case-Study/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AhmetFurkanDEMIR","download_url":"https://codeload.github.com/AhmetFurkanDEMIR/Trendyol-Data-Engineering-Technical-Case-Study/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AhmetFurkanDEMIR%2FTrendyol-Data-Engineering-Technical-Case-Study/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270644765,"owners_count":24621332,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-15T02:00:12.559Z","response_time":110,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apache-spark","case-study","data-engineering","debian","docker","maven","scala","spark","trendyol","trendyoltech","ubuntu"],"created_at":"2024-11-16T15:18:10.911Z","updated_at":"2025-08-15T23:14:20.134Z","avatar_url":"https://github.com/AhmetFurkanDEMIR.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"![](https://img.shields.io/badge/Debian-A81D33?style=for-the-badge\u0026logo=debian\u0026logoColor=white) ![](https://img.shields.io/badge/Docker-2CA5E0?style=for-the-badge\u0026logo=docker\u0026logoColor=white) ![](https://img.shields.io/badge/Apache_Spark-FFFFFF?style=for-the-badge\u0026logo=apachespark\u0026logoColor=#E35A16) ![](https://img.shields.io/badge/Scala-DC322F?style=for-the-badge\u0026logo=scala\u0026logoColor=white)\n\n# Trendyol Data Engineering Technical Case\n\nBu Case çalışmasında iki ayrı görev için iki ayrı Job yazılmıştır. Kodlar **Scala** ile geliştirilmiş ve **SQL** kullanılmamıştır. Spark, bir master iki worker olacak şekilde docker ile deploy edilmiştir.\n\n### **Veri**\n\n```\norders\n |-- customer_id: string\n |-- location:    string\n |-- seller_id:   string\n |-- order_date:  string\n |-- order_id:    string\n |-- price:       double\n |-- product_id:  string\n |-- status:      string\n\nproducts\n |-- brandname:    string\n |-- categoryname: string\n |-- productid:    string\n |-- productname:  string\n```\n\n#### *Problem 1 - Job1*\n\nHer ürün için aşağıdakileri hesaplayın ve dosya sistemine sonuçları yazın:\n- net satış adedi ve tutarı (toplam satış adetleri - iptal / iade adetleri)\n- brüt satış adedi ve tutarı (toplam satış adetleri)\n- **satıldığı** son 5 gündeki satış sayısı ortalamaları\n- en çok sattığı yer\n\n#### *Problem 2 - Job2*\n\nÜrün bazlı fiyat değişimlerini tarihleriyle birlikte çıkarıp dosya sistemine yazın.\n\nBurada `orders` verisi üzerinde aynı `product_id`'nin sonraki order'da fiyatı arttıysa `rise`, azaldıysa `fall` gibi bir çıktı üretebilirsiniz.\n\n\n## **Çözüm**\n\n* [Start.sh](/start.sh)\n\n* [docker-compose.yml](/docker-compose.yml)\n\n* [raw-data](/raw-data)\n\n    * [Orders.json](/raw-data/orders.json)\n\n    * [Products.json](/raw-data/products.json)\n\n* [out_data](/out_data/)\n\n    * [Job1 Out](/out_data/job1/_temporary/0/task_202312110730164091740487195813030_0050_m_000000/part-00000-7d5b6f8e-db19-4066-aec9-f332a8026744-c000.csv)\n\n    * [Job2 Out](/out_data/job2/_temporary/0/task_202312110730004615437569356012626_0012_m_000000/part-00000-9b4f1c2a-04d3-4ca4-987b-3d1b70934676-c000.csv)\n\n    * [Output Join](/out_data/output_join/_temporary/0/task_202312110729476044888576980888494_0005_m_000000/part-00000-0ae58b24-83d3-44c6-a465-36fe44908fa2-c000.csv)\n\n* [spark-submitter](/spark-submitter)\n\n    * [Dockerfile](/spark-submitter/Dockerfile)\n\n    * [spark-submit.sh](/spark-submitter/spark-submit.sh)\n    \n    * [Job1.jar](/spark-submitter/Job1-1.0-SNAPSHOT-jar-with-dependencies.jar)\n\n    * [Job2.jar](/spark-submitter/Job2-1.0-SNAPSHOT-jar-with-dependencies.jar)\n\n* [spark-scala-source-code](/spark-scala-source-code)\n\n    * [Job1](/spark-scala-source-code/Job1/)\n\n        * [Job1.scala](/spark-scala-source-code/Job1/src/main/scala/myPackage/Job1.scala)\n\n        * [Transactions.scala](/spark-scala-source-code/Job1/src/main/scala/myPackage/Transactions.scala)\n\n    * [Job2](/spark-scala-source-code/Job2/)\n\n        * [Job2.scala](/spark-scala-source-code/Job2/src/main/scala/myPackage/Job2.scala)\n\n        * [Transactions.scala](/spark-scala-source-code/Job2/src/main/scala/myPackage/Transactions.scala)\n\n\n\n#### **İşlemleri başlatma | Çıktıları hesaplama**\n\n![](/images/schema.png)\n\nBu bölümde, Docker imajlarını otomatik olarak başlatarak iki görevin de tamamlanmasını ve çıktıların dosya sistemine yazılmasını sağlayacağız.\n\n**Gereklilikler**\n\n* Bilgisayarınızda [Docker](https://docs.docker.com/engine/install/)'ın kurulu olduğundan emin olun.\n\n* Bilgisayarınızda 8080 ve 7077 portlarının boşta ve kullanılabilir olduğundan emin olun.\n\nİşlemlerin başlayabilmesi için [start.sh](/start.sh) dosyasını çalıştırmanız gerekiyor. Bu dosyadaki komutlar Linux komutları içerdiği için, Debian(Ubuntu) tabanlı bir işletim sistemini tercih etmeniz önerilir. Eğer Windows kullanıyorsanız, lütfen dosya içindeki komutları tek tek elle çalıştırın.\n\n\n```terminal\n# işlemlerin başlaması\n\nsudo bash ./start.sh\n```\n\nBu dosyanın çalıştırılmasıyla birlikte, sırasıyla şu adımlar gerçekleştirilecek:\n\n    1. Eğer mevcut bir imaj çalışıyorsa, bu imaj durdurulacak.\n    \n    2. out-data klasörü temizlenecek, yani içindeki dosyalar silinecek.\n    \n    3. spark-network adında bir ağ oluşturulacak.\n    \n    4. İmajlar yeniden oluşturulacak (build) ve ayağa kaldırılacak.\n\n**konteynerların ayağa kalkması**\n\n![](/images/docker_run.png)\n\nArdından, Spark master ve iki worker ayağa kaldırılacak. Spark işlemleri tamamlandıktan sonra, spark-submit adlı konteyner, joblarımızın jar dosyalarını çalıştıracak ve jobların başarıyla tamamlanmasını bekleyecektir. Spark UI'ı görüntülemek için tarayıcınızı açın ve [0.0.0.0:8080](http://0.0.0.0:8080/) adresine gidin.\n\n**Spark kaynak yönetimi**\n\n* **Spark Master** CPU:8, RAM: 16\n\n* **Spark Worker-1** CPU:8, RAM: 8\n\n* **SPARK Worker-2** CPU:8, RAM: 8\n\n**Spark UI [0.0.0.0:8080](http://0.0.0.0:8080/)**\n\n![](/images/spark_ui.png)\n\nJoblar başarıyla tamamlandıktan sonra, *worker1* ve *worker2* üzerinden elde edilen çıktılar alınacak ve bu çıktılar [out_data](/out_data/) klasörüne taşınacaktır.\n\nTüm bu işlemler, genellikle 2-3 dakika içerisinde tamamlanır ve çıktı dosyalarımız kullanılabilir hale gelir.\n\n**Çıktılar**\n\n![](/images/out_data.png)\n\n*Çıktı isimleri değişiklik gösterebilir*\n\n#### **Spark\u0026Scala Kod Çözümü**\n\nÇözümde **Spark'ın 3.5.0** sürümü, **Java'nın 8** sürümü ve **Scala'nın 2.12.8** sürümü kullanılmıştır. Spark kütüphanesini bağımlılıklar için çözüm sürecinde Maven kullanılmıştır.\n\n**Job1**\n\nSpark, *myPackage.Job1* sınıfını çalıştırır. Bu sınıf içinde, iki dosya okunduktan sonra *Transactions* sınıfında dosyalar birleştirilir, işlemler tamamlanır ve elde edilen yeni çıktı dosya sistemine yazılır.\n\n*İşlemler ve metodları*\n\n* dosyaları joinleme **:** Transactions.joinDataFrames\n\n* net satış adedi ve tutarı (toplam satış adetleri - iptal / iade adetleri) **:** Transactions.calculateNetSales\n\n* brüt satış adedi ve tutarı (toplam satış adetleri) **:** Transactions.calculateGrossSales\n\n* satıldığı son 5 gündeki satış sayısı ortalamaları **:** Transactions.calculateAverageSalesPerProduct\n\n* en çok sattığı yer **:** Transactions.calculateMostSoldLocationForAllProducts\n\n* verilerin joinlenmesi **:** Transactions.joinFinalData\n\n* verilerin dosya sistemine yazılması **:** Transactions.writeDataFrame\n\n\n**Job2**\n\nSpark, *myPackage.Job2* sınıfını çalıştırır. Bu sınıf içinde, iki dosya okunduktan sonra *Transactions* sınıfında dosyalar birleştirilir, işlemler tamamlanır ve elde edilen iki yeni çıktı dosya sistemine yazılır.\n\n* dosyaları joinleme **:** Transactions.joinDataFrames\n\n* Joinlenmiş datayı dosya sistemine yazma **:** Transactions.writeJoinData\n\n* Ürün bazlı fiyat değişimleri tarihleriyle birlikte **:** Transactions.calculatePriceChanges\n\n* oluşan çıktıyı dosya sistemine yazma **:** Transactions.writeDataFrame\n\n#### **Oluşabilecek Hatalar**\n\n* **Port Çakışması** 8080 ve 7077 portlarının boş olduğundan emin olun.\n\n* **Docker'ın kurulu olduğundan emin olunuz**\n\n* **Docker sürümü** bazı sürümlerde *docker-compose up* kullanılırken bazı sürümlerde ise *docker compose up* kullanılır. Hata alırsanız bu iki komuttan birini kullanarak çözünüz.\n\n**[Ahmet Furkan Demir](https://ahmetfurkandemir.com/)**","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fahmetfurkandemir%2Ftrendyol-data-engineering-technical-case-study","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fahmetfurkandemir%2Ftrendyol-data-engineering-technical-case-study","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fahmetfurkandemir%2Ftrendyol-data-engineering-technical-case-study/lists"}