Odoo-n eskaeretatik, Helpdesk tiketetatik eta denbora-erregistrotik fakturatzen duenak emaitza ezagutzen du: bezero batek hilaren amaieran ez du faktura bakarra jasotzen, bost baizik. Bakoitza eskaera edo tiketa desberdin batetik dator, bakoitza teknikoki zuzena da – eta, hala ere, bezeroak galdetzen du ea ez ote zen dokumentu bakarrean sartuko.
Hain zuzen ere horretarako ez dago irtenbide garbirik Odoo 19 Community-n. OCA-ren account_invoice_merge modulu ezaguna oraindik ez dago Odoo 19rako argitaratuta, eta zerbitzu-hornitzaileentzat arrisku larria den moduan ebazten du arazoa: lerro berdinak bateratzen dira, eta horrekin eskaerarako, atazarako eta erregistratutako denborarako lotura galtzen da.
Gure Odoo 19 Community instalaziorako, horregatik, Merge Draft Invoices modulua garatu dugu. Arazo hori ez digu gu bakarrik eragiten; beraz, AGPL-3 lizentzia librearekin doan jartzen dugu eskura GitHub-en.
GitHub-eko proiektura:
Zergatik modulu propioa OCA irtenbidearen ordez?
OCA-k aspalditik mantentzen du account_invoice_merge OCA/account-invoicing biltegian. Artikulu honen unean, 19.0rako migrazioa Pull Request ireki bat besterik ez da bertan, ez argitaratutako modulu bat.
Garrantzitsuagoa da, hala ere, bi moduluek gauza desberdinak egiten dituztela:
| OCA account_invoice_merge | Merge Draft Invoices | |
|---|---|---|
| Emaitza | hautatutako fakturetako batean bateratzen da | beti faktura berri bat |
| Lerroak | lerro berdinak bateratzen dira, kopuruak batzen dira | lerro bakoitza aldatu gabe, bat-batekoan hartzen da |
| Jatorria | invoice_origin / payment_reference goiburuan elkarri lotuta | jatorri-eremuak lerro bakoitzeko, Odoo-ren berezko _copy_data_extend_business_fields hook-aren bidez kopiatuta |
| Denbora-erregistroa | kontuan hartu gabe | timesheet_invoice_id faktura berrira aldatzen da |
| Bezeroarentzat irakurgarria | ezer ez | iturri bakoitzaren lerroen gaineko izenburu bat, eskaerarekin eta tiketarekin |
| Iturburu-fakturak | ezeztatzen dira | ezeztatu (lehenetsia), ezabatu edo mantendu – ondorio garbiki izendatuekin |
Lerro berdinak bateratzea da alde erabakigarria. Bateratutako lerro batek jatorri bakarra eraman dezake. Bi eskaera desberdinetako bi lerro berdin ikusten diren bezain pronto, fakturatik eskaerara, atazara eta denbora-erregistrora doan lotura galtzen da. Fakturazioa Tiketa → Denbora-erregistroa → Faktura bidez egiten den zerbitzu-enpresa batean, horrek esan nahi du: ordu berberak bikoiztuta kobratzen dira edo desagertzen dira.
Gure moduluak, beraz, printzipioz ez du ezer bateratzen. Bateratutako fakturak bere iturriek elkarrekin dituzten lerro-kopuru bera du zehazki.
Ez da OCA moduluko koderik hartu. Bi moduluak AGPL-3 lizentziapean daude.
Zer egiten duen moduluak
Faktura-zerrendaren ikuspegian zirriborro bat edo gehiago markatu, ekintza-menuan Faktura-zirriborroak bateratu hautatu – laguntzaile batek hautaketa, egiaztapenak eta iturburu-fakturen aukerak erakusten ditu. Berretsi ondoren, zuzenean faktura berrira iristen da.
Bateratu aurretik moduluak egiaztatzen du, eta puntu guztiak aldi berean, zuzenketa bakoitzaren ondoren hurrengo akatsa ikusi behar ez izateko:
- gutxienez bi faktura hautatuta
- guztiak Zirriborro egoeran
- inoiz ez da bat ere kontabilizatu (zirriborrora berrezarritako dokumentu batek bere kontabilizazio-historia mantentzen du eta baztertu egiten da)
- bat ere ez da lehendik bateratu
- guztiak faktura, hornitzaileen faktura, abonu-ohar edo dokumentu dira – ez kontabilitate-apunte hutsak
- bazkide, dokumentu-mota, enpresa, moneta eta egunkari berberak
Ordainketa-baldintzan, zerga-esleipenean, entrega-helbidean, banku-kontuan edo saltzailean dauden aldeek ez dute blokeatzen. Laguntzaileak abisua ematen du eta hautatutako faktura zaharrenaren balioa hartzen du.
Zer gordetzen den
Moduluaren muina da faktura-lerro batek bere jatorriarekin duen lotura guztiak faktura berrian ere badaudela:
| Lotura | Tratamendua |
|---|---|
| Salmenta-eskaeraren lerroak (sale_line_ids) | lerro bakoitzeko kopiatua Odoo-ren _copy_data_extend_business_fields bidez |
| Erosketa-eskaeraren lerroak (purchase_line_id) | berdin |
| Kostu-zentroen banaketa (analytic_distribution) | lerro bakoitzeko kopiatua |
| beste jatorri-eremu batzuk lerroko | automatikoki, hornitzen duen moduluak dokumentatutako Odoo hook-a inplementatzen badu |
| Jatorria eta erreferentzia faktura-goiburuan | bateratuta, bikoiztu gabe, laguntzailean editagarria |
| Salmenta-eskaera: invoice_ids, invoice_status, qty_invoiced | lerroetatik kalkulatzen dira – eskaerak berak antzematen du faktura berria |
| Denbora-erregistroa (timesheet_invoice_id) | faktura berrira aldatzen da, iturriak baliogabetu aurretik |
| Helpdesk tiketa | denbora-erregistroari lotuta dago eta, beraz, automatikoki faktura berrira seinalatzen du |
| Chatter | mezua faktura berrian iturri guztiekin, mezua iturri bakoitzean faktura berrirako estekarekin |
| merged_into_move_id / merged_from_move_ids | gordetako lotura bi norabideetan |
Zerga-lerroak, ordainketa-baldintzen lerroak, borobiltze- eta ordainketa-azkarreko deskontu-lerroak ez dira kopiatzen, Odoo-k edukitik kalkulatzen ditu berriro. Bateratutako fakturak, beraz, zerga-lerro bat du zerga-tasa bakoitzeko, ez bat iturri bakoitzeko. Zenbakirik gabeko zirriborro gisa sortzen da; bateratzeak berak ez du dokumentu-zenbakirik kontsumitzen.
Izenburuak: bezeroak ikusten du lerro bakoitza nondik datorren
Hori da egunerokoan aldea egiten duen funtzioa. Iturburu-faktura bakoitzaren lerroen gainean, moduluak atal-lerro bat jartzen du – Odoo-k berak “Aurrerakinak” atalerako erabiltzen duen elementu bera:
BE10181 <- Izenburua
22,500 x Teknikari-ordua 3.577,50
Azpitotala 3.577,50
BE10182 · Tiketa: HT00219 <- Izenburua
3,000 x Teknikari-ordua 477,00
Azpitotala 477,00
ZENBATEKO GARBIA 4.054,50
Izenburua bezeroak jasotzen duen dokumentuan inprimatzen da, eta Odoo-ren faktura-txosten estandarrak berak gehitzen du atal bakoitzeko azpitotal bat. Horrela bezeroak ikusten du, gainera, zer kostatu den atal bakoitza.
Etiketa iturriak benetan dituenetik osatzen da:
- eskaerak, zuzenean lerroen loturetatik – izenak, beraz, zehatzak dira; eskaera-loturarik ez badago, invoice_origin-eko testu librea erabiltzen da
- tiketak, denbora-erregistroaren bidez zehaztuak – Tiketa: HT00219 edo Tiketak: … gisa erakutsiak, bost arte mugatuta eta “eta beste N”
- bietako bat ere ez badago: iturburu-fakturaren zenbakia, gero haren erreferentzia
- ezer ere ez badago: “Beste lerro batzuk” neutroa, iturri bateko lerroak inoiz isilean gaineko blokean desager ez daitezen
Falta dena kentzen da, ez asmatzen. Tiketa bere zenbaki propioarekin inprimatzen da – helpdesk_mgmt zenbakia, Enterprise-ko ticket_ref edo ereduaren bistaratze-izena – inoiz ez datu-baseko ID-arekin.
Izenburuak bezeroaren hizkuntzan idazten dira, Odoo-k eskaeretatik fakturak sortzean egiten duen bezala. Chatter erabiltzailearen hizkuntzan geratzen da.
Izenburu batek ez du produkturik, kopururik, prezioarik, zergarik, konturik ez kostu-zentroen banaketarik. Ezin ditu batuketak, zerga-oinarria eta kostuen kontabilitatea eragin. Laguntzailean izenburuak desaktibatzen dituenak funtzio hau gabe sortuko litzatekeen faktura bera jasotzen du – proba batek bi emaitzak zentimora arte alderatzen ditu.
Zer gertatzen den iturburu-fakturekin
Laguntzaileak hiru aukera eskaintzen ditu:
- Ezeztatu (lehenetsia, gomendatua). Zirriborro bat ezeztatzeak ez du ondoriorik: ez dago dokumentu-zenbakirik, ez dago apunterik. Fakturak ezeztatutako dokumentu gisa geratzen dira datu-basean, Chatter-ekin eta faktura berrirako estekarekin. Salmenta-eskaerako qty_invoiced-ek ezeztatutako dokumentuak saltatzen ditu, ez da ezer bikoiztuta kontatzen. Sei hilabete geroago ere jarraigarria izango den aukera da.
- Ezabatu. Itzulezina. Chatter-a eta atzerako erreferentzia erregistroarekin batera hiltzen dira; faktura berriko mezua bakarrik geratzen da. Inork gehiago ikusi nahi ez dituen zirriborro bota-eta-erabilekoentzat da egokia.
- Zirriborro gisa utzi. Iturriak irekita geratzen dira. Haien salmenta-eskaerek orduan iturria eta faktura berria fakturatutzat kontatzen dituzte – lana bikoiztuta kobratuta dagoela dirudi, norbaitek zirriborroak eskuz garbitzen dituen arte. Erabakia hartu aurretik alderatu nahi den kasu bakanerako pentsatua. Proba batek bikoiztuta kontatze hori zehazki jasotzen du, inor ez harritzeko.
Mugak – modulua nahita egiten ez duena
Mesedez, irakurri ekoizpenean erabili aurretik:
- Zirriborroak soilik. Kontabilizatutako fakturak ez dira bateratzen. Hori abonu-oharren zeregina da, ez kopiatze-prozesu bat.
- Behin kontabilizatu eta berrezarritako zirriborroak baztertzen dira. Zenbaki bat eta kontabilizazio-historia dute; hori beste dokumentu batean ezkutatzea ez da multzo-ekintza batek isilean egin behar lukeen zerbait.
- Ez da bateratzen bazkideen, monetak, enpresen edo egunkarien artean. Horretarako ez dago balio bakar zentzuzkorik; beraz, moduluak baztertu egiten du, asmatu beharrean.
- payment_reference ez da hartzen. Ordainketa-erreferentzia egituratuek dokumentu bat identifikatzen dute; bi elkarri lotuta ez datoz ezertarako bankuan. Faktura berriak berea jasotzen du kontabilizatzean.
- Aurrerakin-lerroak beste edozein lerro bezala kopiatzen dira. Iturriek sale-ko aurrerakin-lerroak badituzte, emaitza kontabilizatu aurretik egiaztatu behar da.
- timesheet_invoice_id bakarrik aldatzen da automatikoki. account.move-ra Many2one bat duen beste edozein ereduk (berezko fakturazio-exekuzioak, harpidetza-loturak, EDI bidalketak) iturrira seinalatzen jarraitzen du. Horretarako _merge_draft_relink hook-a dago.
- Ez da lerro berdinik bateratzen – nahita. Faktura labur eta txukun bat nahi duenak ez du tokirik hemen, eta jatorri-loturekin ordaindu beharko luke.
- Izenburuak behin soilik sortzen dira bateratzean. Ondoren atal-lerro arruntak dira: editagarriak, ezabagarriak, eta ez dira eguneratzen eskaera edo tiketa geroago berrizendatzen bada.
- Izenburu batek iturburu-faktura osoko tiketak aipatzen ditu, ez lerro bakarrekoak.
Instalazioa Odoo 19 Community-n
Instalazioa Odoo-ren ohiko gehigarri-modulu batena bezala egiten da:
- Moduluaren direktorioa konfiguratutako addons bide batera kopiatu.
- Odoo-n aplikazio-zerrenda eguneratu.
- account_invoice_merge_draft modulua instalatu.
Moduluak account-en mende soilik dago. Sale, purchase, project, hr_timesheet, sale_timesheet edo Helpdesk modulu bati buruz dakien guztia exekuzio-unean zehazten da – fakturazio-datu-base huts batean ere instalatzen eta funtzionatzen du.
Ondoren: Kontabilitatea → Bezeroak → Fakturak (edo Hornitzaileak → Fakturak), zirriborro bat edo gehiago markatu, engranaje-menua → Faktura-zirriborroak bateratu. Ekintza Fakturazioa taldeko erabiltzaile guztien eskura dago.
Moduluaren aurreko bertsio batetik eguneratzen duenak behin -u account_invoice_merge_draft --i18n-overwrite eguneratu beharko luke, eremu-izenen aldaketak alemanezko itzulpenean ager daitezen. Instalazio berriari ez dio eragiten.
Garatzaileentzat: API eta hook-ak
Bateratzea geure kodetik ere dei daiteke:
python
merged = draft_moves.merge_draft_moves(
extra_vals={"invoice_date": date(2026, 3, 31), "ref": "Q1"},
source_handling="cancel", # "delete" edo "keep"
add_source_sections=True, # Izenburuak; lehenetsia True
)
merge_draft_moves-ek UserError bat jaurtitzen du baztertzeko arrazoi guztiekin, hautaketa bateratu ezin bada. _merge_draft_get_errors()-ek arrazoi berberak itzultzen ditu zerrenda gisa, salbuespenik gabe.
account.move-ra atzerako erreferentzia propioak dituenak _merge_draft_relink gainidazten du:
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}
)
Faktura-lerroan atzerako erreferentzia bat duenak ez du modulu hau batere behar: Odoo-ren berezko account.move.line._copy_data_extend_business_fields hook-a nahikoa da, eta eremua bateratzean, ezeztatzean eta bikoizterakoan berdin hartzen da. Beste Helpdesk modulu batzuetarako edo izenburuen beste formulazio baterako _merge_draft_get_source_tickets() eta _merge_draft_section_name() daude.
Probatua, ekoizpen-datuetan ibili aurretik
48 probak estaltzen dituzte egoera mistoak, bazkide, moneta eta dokumentu-mota desberdinak, salmenta- edo erosketa-eskaerarekin eta gabeko lerroak, zergak, atalak eta oharrak, kostu-zentroen banaketak, denbora-erregistroaren aldaketa, iturburu-fakturetarako hiru aukerak, laguntzailea eta izenburuak – lehenespenez aktibo daudela, desaktibatzeak emaitza zaharra zentimora arte erreproduzitzen duela, izenburu batek ez duela zenbatekorik edo konturik, iturri bateko lerroak elkarrekin geratzen direla, tiketa bere zenbakiarekin agertzen dela eta inoiz ez datu-baseko ID-arekin.
Proba-datuak enpresa aktiboaren kontu-plan existentean oinarritzen dira, AccountTestInvoicingCommon-en ordez – helper hori askotan ez da abiatzen migratutako ekoizpen-datu-baseetan, eta modulua hain zuzen horietan ibili behar da.
odoo-bin -d <db> -u account_invoice_merge_draft --test-enable \
--test-tags /account_invoice_merge_draft --stop-after-init
Kontabilitate-eremuko edozein hedapenekin bezala, gomendatzen dugu instalazioa lehenik proba-ingurune batean egiaztatzea, geure datu-basearen kopia batekin.
Doan eta kode irekian Odoo Community-rako
Biricon IT Services GmbH-n irtenbideak lehenik gure eragiketetako behar zehatzetarako garatzen ditugu. Horretatik erabilera orokorrerako modulu bat sortzen bada, ez dugu instalazio bakar batean ezkutatu nahi.
Merge Draft Invoices, beraz, doan dago eskuragarri kode irekiko proiektu gisa. Iturburu-kodea ikusi, aztertu, egokitu eta AGPL-3 lizentziaren esparruan garatzen jarraitu daiteke.
Gure helburua ez zen ahalik eta faktura laburrena izatea, urtebete geroago ere lerro bakoitzak bere eskaerara, bere tiketara eta bere denbora-erregistrora garamatzan faktura baizik.
Proiektua, iturburu-kodea eta parte-hartzea
Iturburu-kode osoa, instalazio-oharrak eta dokumentazio teknikoa GitHub-en daude eskuragarri:
Ireki Odoo 19 Merge Draft Invoices GitHub-en
Pozik hartzen ditugu praktikako esperientziak, akats-txostenak, hobekuntza-proposamenak eta Odoo Community-ren ekarpenak.
Doan. Jarraigarria. Kode irekia. Odoo 19 Community-rako.