İçereği Atla

Odoo 19 Community: Taslak faturaları birleştirme – açık kaynaklı Merge Draft Invoices modülümüz

18 Eylül 2026 yazan
Odoo 19 Community: Taslak faturaları birleştirme – açık kaynaklı Merge Draft Invoices modülümüz
Alexander Biringer | Biricon IT Services GmbH

Odoo'da siparişlerden, Helpdesk taleplerinden ve zaman kayıtlarından faturalandıranlar sonucu bilir: Bir müşteri ay sonunda tek bir fatura değil, beş fatura alır. Her biri farklı bir siparişten veya taleptan geliyor, her biri içerik olarak doğru – ve yine de müşteri bunların tek bir belgeye sığıp sığmayacağını soruyor.

Odoo 19 Community'de tam da bunun için temiz bir çözüm yok. Bilinen OCA modülü account_invoice_merge Odoo 19 için henüz yayımlanmadı ve sorunu, hizmet sağlayıcılar için ciddi bir risk oluşturan bir şekilde çözüyor: Aynı kalemler birleştiriliyor ve böylece siparişe, göreve ve kaydedilen zamana geri giden bağlantı kayboluyor.

Bu yüzden kendi Odoo 19 Community kurulumumuz için Merge Draft Invoices modülünü geliştirdik. Bu sorun yalnızca bizi ilgilendirmediği için modülü özgür AGPL-3 lisansı altında GitHub'da ücretsiz olarak sunuyoruz.

GitHub'daki projeye git:

Odoo 19 Merge Draft Invoices

Neden OCA çözümü yerine kendi modülümüz?

OCA, account_invoice_merge'i uzun yıllardır OCA/account-invoicing deposunda sürdürüyor. Bu yazının yazıldığı sırada 19.0'a geçiş orada hâlâ açık bir pull request olup yayımlanmış bir modül değil.

Ancak daha önemlisi, iki modülün farklı şeyler yapmasıdır:


OCA account_invoice_mergeMerge Draft Invoices
Sonuçseçilen faturalardan birine birleştirilirher zaman yeni bir fatura
Kalemleraynı kalemler birleştirilir, miktarlar toplanırher kalem bire bir devralınır
Kaynakinvoice_origin / payment_reference başlıkta birbirine eklenirkaynak alanları, her kalem için Odoo'nun kendi _copy_data_extend_business_fields hook'u üzerinden kopyalanır
Zaman kaydıdikkate alınmaztimesheet_invoice_id yeni faturaya aktarılır
Müşteri için okunabilirhiçbir şeyher kaynağın kalemlerinin üzerinde sipariş ve talep bilgisini içeren bir başlık
Kaynak faturalariptal ediliriptal etme (varsayılan), silme veya koruma – sonuçları açıkça belirtilmiş şekilde

Aynı kalemlerin birleştirilmesi belirleyici farktır. Birleştirilmiş bir kalem yalnızca tek bir kaynak taşıyabilir. İki farklı siparişten gelen iki satır aynı göründüğü anda, faturadan siparişe, göreve ve zaman kaydına geri giden bağlantı kaybolur. Faturalandırmanın talep → zaman kaydı → fatura zinciriyle yürüdüğü bir hizmet işletmesinde bu, aynı saatlerin iki kez faturalandırılması veya kaybolması anlamına gelir.

Bu nedenle modülümüz prensip olarak hiçbir şeyi birleştirmez. Birleştirilmiş faturanın kalem sayısı, kaynaklarının toplam kalem sayısına tam olarak eşittir.

OCA modülünden hiçbir kod devralınmadı. Her iki modül de AGPL-3 altındadır.

Modül ne yapar

Fatura listesi görünümünde iki veya daha fazla taslağı işaretleyin, eylem menüsünden Taslak faturaları birleştir'i seçin – bir sihirbaz seçimi, kontrolleri ve kaynak faturalar için seçenekleri gösterir. Onayladıktan sonra doğrudan yeni faturaya gelinir.

Birleştirmeden önce modül kontrol eder ve tüm maddeleri tek seferde kontrol eder; böylece her düzeltmeden sonra bir sonraki hatayı görmek zorunda kalınmaz:

  • en az iki fatura seçilmiş olmalı
  • hepsi Taslak durumunda olmalı
  • hiçbiri hiç kaydedilmemiş olmalı (taslağa geri alınmış bir belge kayıt geçmişini korur ve reddedilir)
  • hiçbiri daha önce birleştirilmemiş olmalı
  • hepsi fatura, tedarikçi faturası, alacak dekontu veya makbuz olmalı – salt yevmiye kayıtları olmamalı
  • aynı iş ortağı, belge türü, şirket, para birimi ve yevmiye defteri

Ödeme koşulu, vergi eşlemesi, teslimat adresi, banka hesabı veya satış temsilcisindeki farklılıklar engellemez. Sihirbaz uyarır ve seçilen en eski faturanın değerini devralır.

Neler korunur

Modülün özü, bir fatura kaleminin kaynağıyla sahip olduğu her bağlantının yeni faturada da mevcut olmasıdır:

Bağlantıİşlem şekli
Satış siparişi kalemleri (sale_line_ids)her kalem için Odoo'nun _copy_data_extend_business_fields'ı üzerinden kopyalanır
Satın alma siparişi kalemleri (purchase_line_id)aynı şekilde
Maliyet merkezi dağılımı (analytic_distribution)her kalem için kopyalanır
kalem başına diğer kaynak alanlarısağlayan modül belgelenmiş Odoo hook'unu uygularsa otomatik olarak
Fatura başlığındaki kaynak ve referansbirleştirilir, yinelenenler ayıklanır, sihirbazda düzenlenebilir
Satış siparişi: invoice_ids, invoice_status, qty_invoicedkalemlerden hesaplanır – sipariş yeni faturayı kendiliğinden tanır
Zaman kaydı (timesheet_invoice_id)kaynaklar geçersiz hale gelmeden önce yeni faturaya aktarılır
Helpdesk talebizaman kaydına bağlıdır ve böylece otomatik olarak yeni faturayı gösterir
Chatteryeni faturada tüm kaynakları içeren bir mesaj, her kaynakta yeni faturaya bağlantı içeren bir mesaj
merged_into_move_id / merged_from_move_idsher iki yönde kaydedilen bağlantı

Vergi satırları, ödeme koşulu satırları, yuvarlama ve iskonto satırları kopyalanmaz; Odoo tarafından içerikten yeniden hesaplanır. Dolayısıyla birleştirilmiş faturada her kaynak için değil, her vergi oranı için bir vergi satırı bulunur. Numarasız bir taslak olarak oluşturulur; birleştirmenin kendisi bir belge numarası tüketmez.

Başlıklar: Müşteri her kalemin nereden geldiğini görür

Günlük kullanımda fark yaratan işlev budur. Modül, her kaynak faturanın kalemlerinin üzerine bir bölüm satırı ekler – Odoo'nun kendisinin “Peşinatlar” bölümü için kullandığı öğenin aynısı:

BE10181                                     <- Başlık
  22,500 x Teknisyen saati        3.577,50
                    Ara toplam 3.577,50
BE10182 · Talep: HT00219                   <- Başlık
   3,000 x Teknisyen saati          477,00
                    Ara toplam   477,00
                      NET TUTAR 4.054,50

Başlık, müşterinin alacağı belgeye basılır ve Odoo'nun standart fatura raporu kendiliğinden her bölüm için bir ara toplam ekler. Böylece müşteri her bölümün maliyetini de görür.

Etiket, kaynağın gerçekte sahip olduğu bilgilerden oluşturulur:

  1. siparişler, doğrudan kalem bağlantılarından – adlar bu nedenle tam olarak doğrudur; sipariş bağlantıları eksikse invoice_origin içindeki serbest metin kullanılır
  2. talepler, zaman kaydı üzerinden belirlenir – Ticket: HT00219 veya Tickets: … olarak çıktılanır, beş ile sınırlıdır ve ardından “ve N tane daha” eklenir
  3. ikisi de yoksa: kaynak faturanın numarası, ardından referansı
  4. hiçbiri yoksa: nötr bir “Diğer kalemler”; böylece bir kaynağın satırları hiçbir zaman sessizce üstteki blokta kaybolmaz

Eksik olan atlanır, uydurulmaz. Talep, kendi numarasıyla basılır – helpdesk_mgmt numarası, Enterprise ticket_ref veya modelin görünen adı – asla veritabanı kimliğiyle (ID) değil.

Başlıklar, Odoo'nun siparişlerden fatura oluştururken yaptığı gibi müşterinin dilinde yazılır. Chatter, kullanıcının dilinde kalır.

Bir başlık ürün, miktar, fiyat, vergi, hesap veya maliyet merkezi dağılımı taşımaz. Toplamları, vergi matrahını ve maliyet hesaplamasını etkileyemez. Başlıkları sihirbazda kapatan, bu işlev olmadan oluşacak faturanın tıpatıp aynısını alır – bir test iki sonucu kuruşu kuruşuna karşılaştırır.

Kaynak faturalara ne olur

Sihirbaz üç seçenek sunar:

  • İptal et (varsayılan, önerilen). Bir taslağı iptal etmenin sonucu yoktur: belge numarası yok, kayıt yok. Faturalar, sohbet geçmişi (chatter) ve yeni faturaya bağlantıyla birlikte iptal edilmiş belgeler olarak veritabanında kalır. Satış siparişindeki qty_invoiced iptal edilmiş belgeleri atlar, hiçbir şey iki kez sayılmaz. Altı ay sonra bile izlenebilir kalan seçenek budur.
  • Sil. Geri alınamaz. Chatter ve geri başvuru kayıtla birlikte yok olur; yalnızca yeni faturadaki mesaj kalır. Kimsenin bir daha görmesini istemediği atılabilir taslaklar için anlamlıdır.
  • Taslak olarak bırak. Kaynaklar açık kalır. Bu durumda satış siparişleri kaynağı ve yeni faturayı faturalanmış sayar – iş, biri taslakları elle temizleyene kadar iki kez faturalanmış gibi görünür. Karar vermeden önce karşılaştırma yapmak istenen nadir durum için tasarlanmıştır. Bir test tam olarak bu çift sayımı kayda geçirir, böylece kimseyi şaşırtmaz.

Sınırlar – modülün bilinçli olarak yapmadıkları

Lütfen canlı kullanımdan önce okuyun:

  • Yalnızca taslaklar. Kaydedilmiş faturalar birleştirilmez. Bu bir alacak dekontu işidir, kopyalama işlemi değil.
  • Bir kez kaydedilip geri alınmış taslaklar reddedilir. Bunların bir numarası ve kayıt geçmişi vardır; bunu başka bir belgenin içinde gizlemek, bir toplu işlemin sessizce halletmesi gereken bir şey değildir.
  • Farklı iş ortakları, para birimleri, şirketler veya yevmiye defterleri arasında birleştirme yapılmaz. Bunun için anlamlı tek bir değer yoktur; bu yüzden modül tahmin yürütmek yerine reddeder.
  • payment_reference devralınmaz. Yapılandırılmış ödeme referansları bir belgeyi tanımlar; birbirine eklenmiş iki referans bankada hiçbir şeyle eşleşmez. Yeni fatura, kaydedilirken kendi referansını alır.
  • Peşinat kalemleri diğer kalemler gibi kopyalanır. Kaynaklar sale modülünden peşinat satırları içeriyorsa, sonuç kayıttan önce kontrol edilmelidir.
  • Yalnızca timesheet_invoice_id otomatik olarak aktarılır. account.move'a Many2one alanı olan diğer her model (kendi faturalama çalıştırmaları, abonelik bağlantıları, EDI iletimleri) kaynağı göstermeye devam eder. Bunun için _merge_draft_relink hook'u vardır.
  • Aynı kalemlerin birleştirilmemesi – bilerek. Kısa, derli toplu bir fatura isteyen kişi burada yanlış yerdedir ve bunun bedelini kaynak bağlantılarıyla öderdi.
  • Başlıklar yalnızca birleştirme sırasında bir kez oluşturulur. Sonrasında normal bölüm satırlarıdır: düzenlenebilir, silinebilir ve sipariş veya talep sonradan yeniden adlandırılırsa güncellenmez.
  • Bir başlık, tek tek kalemin değil, kaynak faturanın tamamının taleplerini belirtir.

Odoo 19 Community'de kurulum

Kurulum, olağan bir Odoo ek modülünde olduğu gibi yapılır:

  1. Modül klasörünü yapılandırılmış bir addons yoluna kopyalayın.
  2. Odoo'daki uygulama listesini güncelleyin.
  3. account_invoice_merge_draft modülünü kurun.

Modül yalnızca account'a bağlıdır. sale, purchase, project, hr_timesheet, sale_timesheet veya bir Helpdesk modülü hakkında bildiği her şey çalışma zamanında belirlenir – saf bir faturalama veritabanında da kurulur ve çalışır.

Sonrasında: Muhasebe → Müşteriler → Faturalar (veya Tedarikçiler → Faturalar), iki veya daha fazla taslağı işaretleyin, dişli menüsü → Taslak faturaları birleştir. Eylem, Faturalama / Fatura düzenleme grubuna sahip tüm kullanıcılar tarafından kullanılabilir.

Modülün önceki bir sürümünden güncelleme yapanlar, değişen alan etiketlerinin Almanca çeviriye yansıması için bir kez -u account_invoice_merge_draft --i18n-overwrite ile güncelleme yapmalıdır. Yeni kurulum bundan etkilenmez.

Geliştiriciler için: API ve hook'lar

Birleştirme kendi kodunuzdan da çağrılabilir:

python

merged = draft_moves.merge_draft_moves(
    extra_vals={"invoice_date": date(2026, 3, 31), "ref": "Q1"},
    source_handling="cancel",   # "delete" veya "keep"
    add_source_sections=True,   # başlıklar; varsayılan True
)

merge_draft_moves, seçim birleştirilemiyorsa tüm ret gerekçelerini içeren bir UserError fırlatır. _merge_draft_get_errors() aynı gerekçeleri istisna (exception) oluşturmadan liste olarak döndürür.

account.move'a kendi geri başvurularınız varsa, _merge_draft_relink'i geçersiz kılın (override):

python

class AccountMove(models.Model):
    _inherit = "account.move"

    def _merge_draft_relink(self, new_move):
        super()._merge_draft_relink(new_move)
        if "my_move_id" not in self.env["my.model"]._fields:
            return
        self.env["my.model"].search([("my_move_id", "in", self.ids)]).write(
            {"my_move_id": new_move.id}
        )

Fatura kaleminde bir geri başvurusu olanların bu modüle hiç ihtiyacı yoktur: Odoo'nun kendi hook'u account.move.line._copy_data_extend_business_fields yeterlidir ve alan birleştirmede, iptalde ve çoğaltmada aynı şekilde devralınır. Diğer Helpdesk modülleri veya başlıkların farklı bir ifadesi için _merge_draft_get_source_tickets() ve _merge_draft_section_name() mevcuttur.

Canlı verilerde çalışmadan önce test edildi

48 test; karışık durumları, farklı iş ortaklarını, para birimlerini ve belge türlerini, satış veya satın alma siparişi olan ve olmayan kalemleri, vergileri, bölümleri ve notları, maliyet merkezi dağılımlarını, zaman kaydının aktarılmasını, kaynak faturalar için her üç seçeneği, sihirbazı ve başlıkları kapsar – başlıkların varsayılan olarak etkin olduğunu, kapatılmalarının eski sonucu kuruşu kuruşuna yeniden ürettiğini, bir başlığın tutar veya hesap taşımadığını, bir kaynağın kalemlerinin bir arada kaldığını, talebin numarasıyla göründüğünü ve asla veritabanı kimliğiyle (ID) görünmediğini.

Test verileri, AccountTestInvoicingCommon üzerine değil, etkin şirketin mevcut hesap planı üzerine kuruludur – bu yardımcı sınıf, taşınmış canlı veritabanlarında çoğu zaman başlamaz ve modülün çalışması gereken yer tam olarak bu tür veritabanlarıdır.

odoo-bin -d <db> -u account_invoice_merge_draft --test-enable \
         --test-tags /account_invoice_merge_draft --stop-after-init

Muhasebe alanındaki her eklentide olduğu gibi, kurulumu önce kendi veritabanınızın bir kopyasıyla bir test ortamında denemenizi öneririz.

Odoo Community için ücretsiz ve açık kaynak

Biricon IT Services GmbH olarak çözümleri önce kendi işletmemizdeki somut gereksinimler için geliştiriyoruz. Bundan genel olarak kullanılabilir bir modül çıkarsa, onu tek bir kurulumun içinde saklamak istemiyoruz.

Merge Draft Invoices bu nedenle ücretsiz bir açık kaynak projesi olarak sunulmaktadır. Kaynak kodu incelenebilir, denetlenebilir, uyarlanabilir ve AGPL-3 lisansı çerçevesinde geliştirilmeye devam edilebilir.

Amacımız mümkün olan en kısa fatura değil, bir yıl sonra bile her kalemin siparişine, talebine ve zaman kaydına geri götürdüğü bir fatura oluşturmaktı.

Proje, kaynak kodu ve katkı

Kaynak kodunun tamamı, kurulum notları ve teknik belgeler GitHub'da mevcuttur:

Odoo 19 Merge Draft Invoices'ı GitHub'da aç

Pratik deneyimlere, hata raporlarına, iyileştirme önerilerine ve Odoo Community'den gelen katkılara açığız.

Ücretsiz. İzlenebilir. Açık kaynak. Odoo 19 Community için.