[{"data":1,"prerenderedAt":40},["ShallowReactive",2],{"blog-akaunting-modul-gelistirme-rehberi":3},{"html":4,"toc":5,"faq":27},"\u003Cp>Akaunting modül geliştirme, ihtiyacınız olan özelliği çekirdek dosyalara dokunmadan, uygulamanın kendi genişletme noktaları üzerine kurmak demektir. Modül; kendi rotaları, görünümleri, dil dosyaları, migration&#39;ları ve \u003Ccode>module.json\u003C\u002Fcode> tanım dosyası olan, Laravel paketine benzeyen bağımsız bir klasördür. Doğru kurulan bir modül sürüm güncellemesinde silinmez; ama her yeni sürümde bir kez test edilmesi gerekir. Bu yazı hem geliştiriciler hem de geliştirme yaptırmayı düşünen işletme sahipleri için.\u003C\u002Fp>\n\u003Ch2 id=\"cekirdekte-yapilan-degisiklik-neden-kaybolur\">Çekirdekte yapılan değişiklik neden kaybolur?\u003C\u002Fh2>\n\u003Cp>Akaunting güncellendiğinde, çekirdek dosyalar yeni sürümün dosyalarıyla değiştirilir. Fatura şablonunu düzenlemek için bir Blade dosyasını değiştirdiyseniz, giriş sayfasına bir alan eklediyseniz ya da bir denetleyiciye birkaç satır koyduysanız, güncelleme bu değişikliklerin üzerine yazar.\u003C\u002Fp>\n\u003Cp>Bu bir hata değil, güncellemenin doğası. Sonuç ise genellikle şu sırayla yaşanır:\u003C\u002Fp>\n\u003Col>\n\u003Cli>Özelleştirme bugün çalışıyor ve kimse onu hatırlamıyor.\u003C\u002Fli>\n\u003Cli>Bir güncelleme yapılıyor; değişiklik sessizce kayboluyor ya da yeni kodla çakışıp hata veriyor.\u003C\u002Fli>\n\u003Cli>Birinin neyin değiştirildiğini hatırlaması, eski dosyayla yenisini karşılaştırması ve değişikliği zaman baskısı altında yeniden yapması gerekiyor.\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>Veritabanına doğrudan eklenmiş bir kolon da benzer bir sorun: uygulama o kolonu tanımadığı için ona hiçbir şey yazmaz, bir sonraki migration da onunla çakışabilir. Çekirdeği değiştirmek bir kez ucuz, her güncellemede ise yeniden pahalıdır. Modül ise bir kez daha pahalı, sonrasında çok daha öngörülebilirdir.\u003C\u002Fp>\n\u003Ch2 id=\"bir-akaunting-modulunun-yapisi\">Bir Akaunting modülünün yapısı\u003C\u002Fh2>\n\u003Cp>Akaunting modülleri, uygulamanın kullandığı modül paketi üzerine kurulu ve arayüzde &quot;App&quot; olarak görünüyor. \u003Ca href=\"https:\u002F\u002Fakaunting.com\u002Fhc\u002Fdocs\u002Fdevelopers\u002Fmodules\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">Akaunting&#39;in geliştirici dokümanına\u003C\u002Fa> göre yeni bir modülün iskeleti şu komutla oluşturuluyor:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">php artisan module:make my-blog\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Komut, \u003Ccode>modules\u002FMyBlog\u002F\u003C\u002Fcode> altında aşağıdakine benzer bir yapı üretir:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-text\">modules\u002FMyBlog\u002F\n├── Console\u002F\n├── Database\u002F\n│   ├── Migrations\u002F\n│   └── Seeds\u002F\n├── Http\u002F\n│   ├── Controllers\u002F\n│   └── Requests\u002F\n├── Jobs\u002F\n├── Listeners\u002F\n├── Models\u002F\n├── Providers\u002F\n│   ├── Event.php\n│   └── Main.php\n├── Resources\u002F\n│   ├── assets\u002F\n│   ├── lang\u002F\n│   └── views\u002F\n├── Routes\u002F\n│   ├── admin.php\n│   └── portal.php\n├── composer.json\n├── module.json\n└── package.json\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Modül bir şirket için şu komutla kurulur; buradaki \u003Ccode>1\u003C\u002Fcode>, şirketin kimliğidir:\u003C\u002Fp>\n\u003Cpre>\u003Ccode class=\"language-bash\">php artisan module:install my-blog 1\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cp>Bu ayrıntı önemli: Akaunting çok şirketli bir uygulama ve modüller şirket bazında etkinleştiriliyor. Modülün oluşturduğu her kaydın hangi şirkete ait olduğunu taşıması ve sorguların bunu gözetmesi gerekiyor.\u003C\u002Fp>\n\u003Ch3 id=\"module-json\">module.json\u003C\u002Fh3>\n\u003Cp>Modülün kimlik kartı. Dokümanda geçen başlıca alanlar:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Ccode>alias\u003C\u002Fcode>: modülün benzersiz kısa adı; uygulamanın her yerinde bu adla anılır\u003C\u002Fli>\n\u003Cli>\u003Ccode>version\u003C\u002Fcode>, \u003Ccode>active\u003C\u002Fcode>, \u003Ccode>icon\u003C\u002Fcode>\u003C\u002Fli>\n\u003Cli>\u003Ccode>providers\u003C\u002Fcode>: modülün servis sağlayıcıları (örneğin \u003Ccode>Main\u003C\u002Fcode>)\u003C\u002Fli>\n\u003Cli>\u003Ccode>requires\u003C\u002Fcode>: bağımlı olduğu diğer modüller\u003C\u002Fli>\n\u003Cli>\u003Ccode>settings\u003C\u002Fcode>, \u003Ccode>reports\u003C\u002Fcode>, \u003Ccode>widgets\u003C\u002Fcode>: modülün ayarlar ekranı, raporları ve gösterge paneli bileşenleri\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Ayarların, raporların ve widget&#39;ların burada bildirimsel olarak tanımlanması, çekirdeğe dokunmadan bu yüzeylere girebilmenizi sağlıyor.\u003C\u002Fp>\n\u003Ch3 id=\"rotalar-ve-iki-ayri-yuzey\">Rotalar ve iki ayrı yüzey\u003C\u002Fh3>\n\u003Cp>\u003Ccode>Routes\u002Fadmin.php\u003C\u002Fcode> yönetim paneli için, \u003Ccode>Routes\u002Fportal.php\u003C\u002Fcode> müşteri portalı için. İkisi farklı kullanıcılara, farklı yetkilere hitap ediyor; menü girişleri de her yüzey için ayrı olaylar dinlenerek ekleniyor.\u003C\u002Fp>\n\u003Ch2 id=\"genisletme-noktalari-cekirdege-dokunmadan-davranis-eklemek\">Genişletme noktaları: çekirdeğe dokunmadan davranış eklemek\u003C\u002Fh2>\n\u003Cp>Bir modülün değeri, çekirdeğin davranışını onu değiştirmeden genişletebilmesinden geliyor. Başlıca mekanizmalar:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Olaylar ve dinleyiciler:\u003C\u002Fstrong> Akaunting birçok işlem sırasında olay yayımlıyor. Modül, \u003Ccode>Providers\u002FEvent.php\u003C\u002Fcode> içinde bu olaylara dinleyici bağlayarak araya girer; menüye giriş eklemek bunun en yaygın örneği.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Observer&#39;lar:\u003C\u002Fstrong> &quot;Bir fatura oluşturulduğunda şunu da yap&quot; türü mantık için. Modülün servis sağlayıcısında kaydedilir ve çekirdek modelin yaşam döngüsüne bağlanır.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>View composer&#39;lar:\u003C\u002Fstrong> bir ekranın bir bölümüne içerik eklemek ya da bir şablonu değiştirmek için. Çekirdek Blade dosyası olduğu gibi kalır.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Job&#39;lar:\u003C\u002Fstrong> Akaunting kayıt oluşturma, güncelleme ve silme işlerini job sınıflarıyla yapıyor. Modülün de aynı yolu izlemesi, mantığın ekrandan, API&#39;den ve konsoldan aynı şekilde çalışmasını sağlıyor.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Kendi tabloları:\u003C\u002Fstrong> modülün ihtiyaç duyduğu veriler, çekirdek tablolara kolon eklemek yerine modülün kendi migration&#39;larıyla oluşturduğu tablolarda tutulmalı.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch3 id=\"yetkiler\">Yetkiler\u003C\u002Fh3>\n\u003Cp>Gözden en çok kaçan adım bu. Dokümana göre modülün yetkileri, kurulum sırasında çalışan \u003Ccode>FinishInstallation\u003C\u002Fcode> dinleyicisinde, \u003Ccode>attachPermissionsToAdminRoles\u003C\u002Fcode> ile yönetici rollerine bağlanıyor. Kontrol ise rol adıyla değil yetkiyle yapılmalı, çünkü kullanıcılar kendi rollerini oluşturabiliyor. Bu adım atlanırsa menü girişi görünür ama tıklanınca 403 hatası döner; &quot;modül bozuk&quot; şikâyetlerinin önemli bir kısmının arkasında bu var.\u003C\u002Fp>\n\u003Ch3 id=\"dil-dosyalari\">Dil dosyaları\u003C\u002Fh3>\n\u003Cp>\u003Ccode>Resources\u002Flang\u003C\u002Fcode> altında Türkçe ve İngilizce dosyaları ilk günden birlikte yazmak, sonradan çevirmekten ucuz. Modül PDF üretiyorsa, Türkçe karakterleri içeren bir yazı tipinin gömülmesi de gerekiyor; aksi halde ı, ş, ğ gibi harfler bozuk çıkabiliyor.\u003C\u002Fp>\n\u003Ch2 id=\"app-store-uygulamasi-mi-ozel-modul-mu\">App Store uygulaması mı, özel modül mü?\u003C\u002Fh2>\n\u003Cp>Teknik olarak ikisi aynı yapıda. Fark, kimin için yazıldığında.\u003C\u002Fp>\n\u003Cdiv class=\"table-scroll\">\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>\u003C\u002Fth>\n\u003Cth>App Store uygulaması\u003C\u002Fth>\n\u003Cth>Özel modül\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\u003Ctr>\n\u003Ctd>Hedef kitle\u003C\u002Ftd>\n\u003Ctd>Bütün Akaunting kullanıcıları\u003C\u002Ftd>\n\u003Ctd>Yalnızca sizin şirketiniz\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Tasarım\u003C\u002Ftd>\n\u003Ctd>Her kurulumda çalışacak kadar genel\u003C\u002Ftd>\n\u003Ctd>Sizin sürecinize göre\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Dağıtım\u003C\u002Ftd>\n\u003Ctd>Onaylı geliştirici hesabı ve inceleme süreci\u003C\u002Ftd>\n\u003Ctd>Kendi repo&#39;nuzdan doğrudan kurulum\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Sahiplik\u003C\u002Ftd>\n\u003Ctd>Geliştiricide, siz lisans alırsınız\u003C\u002Ftd>\n\u003Ctd>Size ait kaynak kod\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Cloud&#39;da kullanım\u003C\u002Ftd>\n\u003Ctd>Mağazada yer alıyorsa mümkün\u003C\u002Ftd>\n\u003Ctd>Pratikte mümkün değil\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Bakım\u003C\u002Ftd>\n\u003Ctd>Geliştiricinin takviminde\u003C\u002Ftd>\n\u003Ctd>Sizin ya da anlaştığınız ekibin takviminde\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\u003C\u002Ftable>\u003C\u002Fdiv>\n\u003Cp>İhtiyacınız App Store&#39;da zaten bir uygulama olarak duruyorsa, çoğu zaman en ucuz yol onu satın almak. Özel modül; ihtiyacın gerçekten size özgü olduğu, mevcut uygulamaların karşılamadığı ya da başka iç sistemlerle entegrasyon gerektiği durumlarda anlam kazanıyor. Türkiye&#39;de bunun tipik örnekleri tevkifat, cari ekstre, çek-senet takibi ve e-Belge bağlantıları; e-Fatura tarafındaki seçenekleri \u003Ca href=\"\u002Fblog\u002Fakaunting-e-fatura\">Akaunting e-Fatura yazımızda\u003C\u002Fa> ayrıca ele aldık.\u003C\u002Fp>\n\u003Ch2 id=\"modulu-surumler-boyunca-ayakta-tutmak\">Modülü sürümler boyunca ayakta tutmak\u003C\u002Fh2>\n\u003Cp>Akaunting&#39;in sürüm politikası, kullanıcıların çekirdek sürümüyle birlikte yayımlanan modül sürümünü kullandığını varsayıyor ve modül geliştiricilerinden geriye dönük uyumluluk beklemiyor. Bu, özel bir modülün bakım ihtiyacı olduğu anlamına geliyor. Pratikte işe yarayan alışkanlıklar:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cinput disabled=\"\" type=\"checkbox\"> \u003Cstrong>Bağımlılık listesi tutun.\u003C\u002Fstrong> Modülün kullandığı çekirdek sınıfları, dinlediği olayları, değiştirdiği görünümleri ve job&#39;ları yazılı bir listede toplayın. Güncellemeden sonra kontrol edilecek liste budur.\u003C\u002Fli>\n\u003Cli>\u003Cinput disabled=\"\" type=\"checkbox\"> \u003Cstrong>Hangi çekirdek sürümüne karşı test edildiğini not edin.\u003C\u002Fstrong> Her modül sürümünün yanında &quot;şu Akaunting sürümüyle doğrulandı&quot; bilgisi olsun.\u003C\u002Fli>\n\u003Cli>\u003Cinput disabled=\"\" type=\"checkbox\"> \u003Cstrong>Otomatik testler yazın.\u003C\u002Fstrong> Laravel&#39;in test altyapısıyla, modülün temel akışlarını (kayıt oluşturma, rapor, yetki) kapsayan birkaç test, her yükseltmede elle tıklamaktan çok daha güvenilir.\u003C\u002Fli>\n\u003Cli>\u003Cinput disabled=\"\" type=\"checkbox\"> \u003Cstrong>Migration&#39;ları eklemeli yazın.\u003C\u002Fstrong> Mevcut migration&#39;ları değiştirmek yerine, her değişiklik için yeni bir migration ekleyin.\u003C\u002Fli>\n\u003Cli>\u003Cinput disabled=\"\" type=\"checkbox\"> \u003Cstrong>Önce kopya ortam.\u003C\u002Fstrong> Çekirdeği yükseltmeden önce, modülü yeni sürümde bir kopya ortamda çalıştırın ve bağımlılık listesini kontrol edin.\u003C\u002Fli>\n\u003Cli>\u003Cinput disabled=\"\" type=\"checkbox\"> \u003Cstrong>Kaynak kodu sizin repo&#39;nuzda tutun.\u003C\u002Fstrong> Modülü yazan kişiyle yollarınız ayrılsa bile, kod ve kurulum talimatları elinizde kalmalı.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>Büyük sürüm geçişlerinde bu alışkanlıkların değeri daha da artıyor; 2.x&#39;ten 3.x&#39;e geçen bir kurulumda çekirdek değişiklikleri ve modüller nasıl ele alınmalı, \u003Ca href=\"\u002Fblog\u002Fakaunting-2x-3x-gecis\">Akaunting 2.x&#39;ten 3.x&#39;e geçiş yazımızda\u003C\u002Fa> anlattık.\u003C\u002Fp>\n\u003Ch2 id=\"isletme-sahibi-icin-bir-modul-teklifinde-neye-bakmali\">İşletme sahibi için: bir modül teklifinde neye bakmalı?\u003C\u002Fh2>\n\u003Cp>Kodu kendiniz okumayacak olsanız bile, bir modül teklifini değerlendirirken sorabileceğiniz net sorular var:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Çekirdek dosyalara dokunulacak mı?\u003C\u002Fstrong> Cevap &quot;evet&quot; ise, her güncellemede bu değişikliğin yeniden yapılması gerekeceğini bilin. Doğru cevap, yalnızca modül içinde çalışılacağıdır.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Kaynak kod kimde kalacak?\u003C\u002Fstrong> Modül sizin hesabınızdaki bir repo&#39;da durmalı ve telif hakkı size ait olmalı.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Hangi Akaunting sürümüne karşı test edilecek?\u003C\u002Fstrong> Teslimde bu bilgi yazılı olmalı.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Yetkiler ve dil dosyaları kapsamda mı?\u003C\u002Fstrong> İkisi de sonradan eklendiğinde pahalıya patlayan işler.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Bir sonraki güncellemede ne olacak?\u003C\u002Fstrong> Modülün yeni sürümlerde kim tarafından, hangi koşullarla doğrulanacağı baştan konuşulmalı. &quot;Bakımı gerekmez&quot; diyen bir teklif, Akaunting&#39;in sürüm politikasıyla uyuşmuyor.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>&quot;Bitti&quot; ne demek?\u003C\u002Fstrong> Kabul kriterleri sıfatlarla değil, test edilebilir cümlelerle yazılmalı.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"nereden-baslamali\">Nereden başlamalı?\u003C\u002Fh2>\n\u003Cp>Bir özelleştirme ihtiyacınız varsa önce iki soruyu cevaplayın: Bu ihtiyaç App Store&#39;daki bir uygulamayla karşılanabiliyor mu? Karşılanmıyorsa, modül tam olarak ne yapmalı ve neyi yapmamalı? İkinci sorunun cevabını kabul kriterleriyle yazıya dökmek, geliştirmeyi kim yaparsa yapsın işin en değerli kısmı. Halihazırda çekirdek dosyalarda yapılmış değişiklikleriniz varsa, onların listesini çıkarmak da iyi bir ilk adım.\u003C\u002Fp>\n\u003Cp>Bu işi birlikte yapmak isterseniz, \u003Ca href=\"\u002Fakaunting\u002Fmodul-gelistirme\">Akaunting modül geliştirme\u003C\u002Fa> hizmetimizde ücretli bir keşifle başlıyor, modülü yalnızca belgelenmiş genişletme noktaları üzerine kuruyor ve kendi repo&#39;nuzda teslim ediyoruz. İhtiyacınızı \u003Ca href=\"\u002Filetisim\">iletişim sayfamızdan\u003C\u002Fa> kısaca anlatabilirsiniz.\u003C\u002Fp>\n",[6,9,12,15,18,21,24],{"id":7,"text":8},"cekirdekte-yapilan-degisiklik-neden-kaybolur","Çekirdekte yapılan değişiklik neden kaybolur?",{"id":10,"text":11},"bir-akaunting-modulunun-yapisi","Bir Akaunting modülünün yapısı",{"id":13,"text":14},"genisletme-noktalari-cekirdege-dokunmadan-davranis-eklemek","Genişletme noktaları: çekirdeğe dokunmadan davranış eklemek",{"id":16,"text":17},"app-store-uygulamasi-mi-ozel-modul-mu","App Store uygulaması mı, özel modül mü?",{"id":19,"text":20},"modulu-surumler-boyunca-ayakta-tutmak","Modülü sürümler boyunca ayakta tutmak",{"id":22,"text":23},"isletme-sahibi-icin-bir-modul-teklifinde-neye-bakmali","İşletme sahibi için: bir modül teklifinde neye bakmalı?",{"id":25,"text":26},"nereden-baslamali","Nereden başlamalı?",[28,31,34,37],{"q":29,"a":30},"Akaunting'de çekirdek dosyaları değiştirmek neden önerilmez?","Çünkü güncelleme, çekirdek dosyaları yeni sürümün dosyalarıyla değiştirir. Elle yapılan her değişiklik ya kaybolur ya da yeni kodla çakışır. Aynı özelleştirme bir modül olarak yapıldığında güncelleme ona dokunmaz; yalnızca modülün yeni sürümle uyumlu olup olmadığını kontrol etmek gerekir.",{"q":32,"a":33},"Akaunting modülü hangi teknolojiyle yazılır?","Akaunting modülleri PHP ile, Laravel paketlerine benzer bir yapıda yazılır. Kendi rotaları, denetleyicileri, modelleri, görünümleri, dil dosyaları ve veritabanı migration'ları olan bağımsız bir klasördür ve module.json dosyasıyla tanımlanır.",{"q":35,"a":36},"Özel modül Akaunting Cloud'da çalışır mı?","Pratikte hayır. Kendi yazdığınız bir modülü barındırılan bir Cloud hesabına kurmanın yolu yok. Özel kod ihtiyacınız varsa, Akaunting'i kendi sunucunuzda çalıştırmanız gerekir.",{"q":38,"a":39},"Modülüm her Akaunting güncellemesinde bozulur mu?","Bozulmak zorunda değil, ama her sürümde doğrulanması gerekir. Akaunting'in sürüm politikası modül geliştiricilerinden geriye dönük uyumluluk beklemiyor; bu yüzden modülün dayandığı çekirdek davranışlarının listesini tutmak ve her yeni sürümde bir kopya ortamda test etmek gerekir.",1793978420915]