Aki az Odoóban csomagokat ad el, például egy mérőműszert tartozékokkal és szereléssel, egy munkahelyet hardverrel és beüzemeléssel, vagy több szolgáltatásból álló karbantartási csomagot, az ajánlatban egyszerre két dologra van szüksége: Az összetételnek szerepelnie kell a megrendelésben, hogy a raktár, a műszaki részleg és a számlázás tudja, mit kell szállítani. Az ügyfélnek szánt nyomtatványon viszont nem minden esetben szerepeljen minden egyes tétel minden egyes egységárral.
Az OCA sale_product_set modulja lehetővé teszi, hogy termékkészleteket (értékesítési darabjegyzékeket) egy kattintással beillesszünk egy ajánlatba. A nyomtatási képről azonban nem dönt. Erre fejlesztettük ki a Sale Product Set Layout modult (sale_product_set_layout). Az Odoo 19-hez készült, és szabad szoftverként az AGPL-3 licenc alatt ingyenesen elérhető a GitHubon:
github.com/Alex0176/odoo-sale-product-set-layout
A cikk tartalma
- A probléma: a termékkészletek nincsenek hatással a nyomtatási képre
- Mit csinál a modul
- A három nyomtatási mód részletesen
- Elrejtett sorok és fix ár
- Technikai megvalósítás
- Telepítés nem kívánt mellékhatások nélkül
- Használat lépésről lépésre
- Tesztek
- Korlátok és jogi megjegyzés
- Gyakori kérdések
- A Biricon IT Services támogatása
A probléma: a termékkészletek nincsenek hatással a nyomtatási képre
Az Odoóban a termékkészlet előre elkészített terméklista mennyiségekkel. Ahelyett, hogy tíz cikket egyenként keresnénk, az ajánlatban a Készlet hozzáadása lehetőséget választjuk, és az összes sor egyszerre megjelenik. Ez időt takarít meg, és megakadályozza, hogy tételek kimaradjanak. A sale_product_set modul a következő tárolóból OCA/sale-workflow pontosan ezt teszi; maguk a készletek a product_set modulból származnak, amely a következő tárolóban található: OCA/product-attribute.
A gyakorlatban három hiányosság marad:
- Nincs felismerhető csoportosítás. A készlet sorai laza tételekként kerülnek az ajánlatba. A beillesztés után már nem látszik, hogy mely sorok tartoznak össze, és a készlet végösszege sehol sem szerepel.
- Nincs hatással a nyomtatványra. Néha az ügyfél minden tételt árral együtt lásson, néha csak a csomagárat, néha csak egyetlen sort. Ez készletenként vagy ügyfelenként eldöntendő kérdés, nem pedig ajánlatonként kézzel újra megoldandó feladat.
- Az árkorrekciók csúnyák. Ha egy csomagnak fix ára van, amely eltér a listaárak összegétől, korrekciós sorra van szükség. Ez a számításba tartozik, de nem feltétlenül az ügyfél papírjára.
Az Odoo 19 tartalmazza az építőelemeket a tiszta megoldáshoz: az ajánlatsorokban szakaszok és alszakaszok az Árak elrejtése és az Összetétel elrejtése beállításokkal (collapse_prices és collapse_composition mezők). A modul a termékkészletet ezekkel a szabványos beállításokkal köti össze ahelyett, hogy saját nyomtatási formátumot találna ki.
Mit csinál a modul
- Készlet beillesztése szakaszként. A Készlet hozzáadása varázsló egy szakaszsort hoz létre a készlet nevével, például 2 × Messkit Standard, és alá helyezi a készlet sorait. A készleten belüli szakaszok alszakaszokká válnak.
- Nyomtatási mód készletenként. A készletben egyszer kell megadni, hogyan nyomtatódjon. Beillesztéskor a mód a varázslóban az adott esetre módosítható.
- Sorok elrejtése. Az egyes sorok Ne nyomtassa (a készletnél: Rejtett) jelöléssel láthatók el. Beleszámítanak az összegbe, de sem nyomtatásra, sem az ügyfélportálon való megjelenítésre nem kerülnek. A jelölés az ajánlatról átkerül a számlára.
- Fix ár készletsoronként. Egy készletsor fix egységárat viselhet, amely felváltja az árlistából származó árat, például egy elrejtett árkorrekcióhoz.
A modul nélkül (csak sale_product_set) | A sale_product_set_layout modullal |
|---|---|
| A készlet sorai laza tételekként | Szakaszsor a készlet nevével, a mennyiség a névben, alatta a sorok |
| A készleten belüli szakaszok szakaszok maradnak, és széttördelik a szerkezetet | A készleten belüli szakaszok alszakaszokká válnak (line_subsection) |
| A nyomtatási kép mindig ugyanaz | Nyomtatási mód készletenként, beillesztéskor módosítható |
| Az árkorrekció látható az ajánlaton és a számlán | A sor elrejthető, de beleszámít az összegbe |
| Az ár kizárólag az árlistából származik | Opcionálisan fix ár készletsoronként |
| A kialakítás az ajánlatnál véget ér | A kialakítás és az elrejtés az ajánlatra, a megrendelésre, a számlára és az ügyfélportálra is érvényes |
A három nyomtatási mód részletesen
A nyomtatási mód a termékkészlet print_mode választómezője. Beillesztéskor a szakaszsor két szabványos kapcsolójára fordítódik le. Erre a modulban egyetlen, könnyen olvasható hozzárendelés szolgál:
# Druckmodus -> (collapse_prices, collapse_composition) der Abschnittszeile
PRINT_MODE_FLAGS = {
"detailed": (False, False),
"total_only": (True, False),
"summary": (False, True),
}
Mód (print_mode) | Megjelenítés a készletben | Szabványos opció az Odoóban | Nyomtatási kép |
|---|---|---|---|
detailed | Minden sor árral | nincs | Szakasz, minden sor összeggel |
total_only | Sorok ár nélkül, csak a készlet összege | collapse_prices (Árak elrejtése) | Szakasz összeggel, a sorok csak megnevezéssel és mennyiséggel |
summary | Csak egy sor a készlet összegével | collapse_composition (Összetétel elrejtése) | Csak a szakaszsor az összeggel |
Mivel a modul az Odoo 19 szabványos beállításait használja, és nem saját nyomtatási formátumot, az ajánlat, a megrendelés-visszaigazolás, a számla és az ügyfélportál módosított jelentéssablonok nélkül is működik. Aki saját jelentéssablonokat használ, amelyek figyelembe veszik a szakaszbeállításokat, ugyanezt a viselkedést kapja.
Elrejtett sorok és fix ár
Gyakori eset: egy csomag csomagára alacsonyabb az egyes árak összegénél. Az egyes árak elferdítése helyett fix árú korrekciós sort veszünk fel (például −50,00 € készletenként), és elrejtjük. A háttérrendszerben a számla követhető, a nyomtatványon pedig a csomagár szerepel.
A megértéshez fontos: a hide_in_report jelölés semmit sem változtat a számításon. A mennyiség, az ár, a kedvezmény, az adó, az összegek és a könyvelési tételek változatlanul a szabványos Odoo révén jönnek létre. A sor csak a nyomtatványról és a portálról hiányzik.
- A termékkészletnél: készletsor Rejtett beállítással és opcionálisan Fix ár az Egységárral együtt.
- Az ajánlat- és számlasorokon: Ne nyomtassa oszlop (
hide_in_report), a készlet nélküli normál sorokhoz is. - Átadás: A számla megrendelésből történő létrehozásakor a jelölés átkerül a számlasorra. Az ajánlat másolásakor megmarad.
Technikai megvalósítás
A modul szándékosan kicsi: meglévő modelleket bővít, és csak azokat a pontokat írja felül, ahol az Odoo eldönti, hogy mely sorok kerülnek nyomtatásra és hogyan kerül beillesztésre egy készlet. Nincsenek új jelentéssablonok, új modellek és SQL-beavatkozások.
Bővített modellek és mezők
| Modell | Kiegészítés |
|---|---|
product.set | insert_as_section mezők (logikai, alapértelmezés szerint bekapcsolva) és print_mode (választó, kötelező mező, alapértelmezés detailed) |
product.set.line | hide_in_report, fixed_price, price_unit mezők; a prepare_sale_order_line_values() továbbadja őket az ajánlatsornak |
sale.product.set.wizard | insert_as_section, section_name, print_mode mezők; a _prepare_order_lines() építi fel a szakaszsort |
sale.order / sale.order.line | hide_in_report mező (copy=True beállítással); a _get_order_lines_to_report() átugorja az elrejtett sorokat; a _prepare_invoice_line() továbbadja a jelölést |
account.move / account.move.line | hide_in_report mező; a _get_move_lines_to_report(), a _get_detailed_lines() és a _get_subsection_lines() kiszűrik az elrejtett sorokat; a _get_aml_vals() beviszi a jelölést a jelentés adataiba |
Elrejtés az ajánlatban
Az Odoo 19 a nyomtatandó ajánlatsorokat a _get_order_lines_to_report() metódusban határozza meg. A modul itt egy szűrőt fűz hozzá. A jelentéssablon módosítására nincs szükség: mind az ajánlat jelentéssablonja (sale/report/ir_actions_report_templates.xml), mind a portálsablon (sale/views/sale_portal_templates.xml) ezt a metódust hívja meg:
class SaleOrder(models.Model):
_inherit = "sale.order"
def _get_order_lines_to_report(self):
return super()._get_order_lines_to_report().filtered(
lambda line: not line.hide_in_report
)
Átadás a számlára
Amikor a számlasor az ajánlatsorból létrejön (_prepare_invoice_line()), a jelölés átmásolódik. A számla oldalán az Odoo 19-ben több útvonalon keresztül kerülnek sorok a jelentésbe: a főlista, egy szakasz sorai és egy alszakasz sorai. Ezért a modul több helyen szűr (_get_move_lines_to_report() a bizonylaton, _get_detailed_lines() és _get_subsection_lines() a soron), különben egy elrejtett sor egy másik úton ismét felbukkanhatna:
class AccountMoveLine(models.Model):
_inherit = "account.move.line"
hide_in_report = fields.Boolean(string="Hidden in report")
def _get_aml_vals(self, hide_taxes):
res = super()._get_aml_vals(hide_taxes)
res["hide_in_report"] = self.hide_in_report
return res
def _get_detailed_lines(self, children_lines, direct_children_lines, subsection_lines):
res = super()._get_detailed_lines(children_lines, direct_children_lines, subsection_lines)
return [vals for vals in res if not vals.get("hide_in_report")]
def _get_subsection_lines(self, subsection_line, children_lines):
res = super()._get_subsection_lines(subsection_line, children_lines)
return [vals for vals in res if not vals.get("hide_in_report")]
A varázsló: szakasz laza sorok helyett
A sale_product_set modul sale.product.set.wizard varázslója a _prepare_order_lines() metódusban állítja elő az ajánlatsorokat. A modul felülírja ezt a metódust. Ha a Beillesztés szakaszként ki van kapcsolva, egyszerűen az eredeti metódust hívja meg, a viselkedés ilyenkor megegyezik az OCA-modulével. Ellenkező esetben először a két szabványos kapcsolóval ellátott szakaszsor jön létre, majd a készlet sorai következnek. A készleten belüli szakaszok alszakaszokká válnak, hogy ne törjék szét a fő szerkezetet:
def _prepare_order_lines(self):
if not self.insert_as_section:
return super()._prepare_order_lines()
sequence = self._get_max_sequence() + 1
collapse_prices, collapse_composition = PRINT_MODE_FLAGS[self.print_mode or "detailed"]
order_lines = [Command.create({
"display_type": "line_section",
"name": self.section_name or self.product_set_id.name,
"sequence": sequence,
"collapse_prices": collapse_prices,
"collapse_composition": collapse_composition,
})]
for set_line in self._get_lines():
sequence += 1
values = set_line.prepare_sale_order_line_values(self.order_id, self.quantity, sequence)
if values.get("display_type") == "line_section":
values["display_type"] = "line_subsection"
order_lines.append(Command.create(values))
return order_lines
Döntések, amelyeket nem látni
- Különálló számítási metódusok a varázslóban. A szakasz neve, a nyomtatási mód és a Beillesztés szakaszként mind külön
computemetódust kap (store=True,readonly=False). Ha mindhárom ugyanazt a metódust használná, az egyik mezőnek kifejezetten átadott érték visszaállítaná a többit. Ez főleg akkor tűnik fel, ha a varázslót kódból vagy tesztekből hozzák létre értékekkel. - Szakasznév a mennyiséggel. Ha a mennyiség nem 1, szerepel a névben (2 × Messkit Standard, tizedesvesszővel), hogy a nyomtatványon látszódjon: két készletről van szó, és nem egy kétszeres mennyiségű készletről.
- Fix ár csak a termékes soroknál. A
prepare_sale_order_line_values()csak akkor állítja be ahide_in_reportés aprice_unitértékét, ha a készletsor nem szakasz- vagy megjegyzéssor. - Szabványos Odoo saját építés helyett. A nyomtatási mód és az elrejtés az Odoo 19 meglévő kapcsait és mezőit használja. Ez kezelhetővé teszi a frissítéseket: ha az Odoo megváltoztatja a jelentéssablont, a modul érvényes marad, amíg a metódusok léteznek.
Telepítés nem kívánt mellékhatások nélkül
Előfeltételek: Odoo 19.0, sale_product_set (OCA/sale-workflow, 19.0 ág) és product_set (OCA/product-attribute, 19.0 ág). Maga a modul a sale_management, a sale_product_set és az account moduloktól függ.
Az auto_install csapda az OCA-moduloknál. Sok OCA-tároló tartalmaz auto_install beállítású modulokat. Amint a függőségeik rendelkezésre állnak, az Odoo a következő telepítéskor vagy frissítéskor kérdés nélkül telepíti őket. Aki ezért a teljes OCA-tárolót egy éles példány addons_path útvonalára teszi, könnyen olyan modulokat kaphat, amelyeket senki sem akart. Az OCA/product-attribute esetében ez például a purchase_product_template_tags modult érinti. Az eljárásunk:
- A két OCA-tárolót sekélyen klónozzuk (
git clone --depth 1 --branch 19.0). - Egy saját könyvtárban csak a két szükséges modult linkeljük szimbolikus hivatkozással, és ezt a könyvtárat vesszük fel az
addons_pathútvonalba, nem a teljes tárolókat. - Tesztadatbázison telepítjük, és ellenőrizzük, mely modulok kapnak eközben telepítve állapotot.
- Csak ezután telepítjük élesben, a
--workers=0kapcsolóval, hogy a hívás ne versenyezzen a futó szolgáltatással a HTTP-portért.
odoo-bin -c /etc/odoo/odoo.conf -d <datenbank> -i sale_product_set_layout --stop-after-init
Az új mezők és nézetek a telepítés után az adatbázisban vannak. Ha a szolgáltatás többfolyamatos üzemmódban fut, a workerek az adatbázis-jelzés révén újratöltik a megváltozott registryt. A modul Python-fájljainak módosításai csak a szolgáltatás újraindítása után lépnek érvénybe.
Használat lépésről lépésre
- Készlet létrehozása: Értékesítés → Termékek → Termékkészletek. Nevezze el a készletet, válassza a Beillesztés szakaszként és a Nyomtatási mód beállítást, írja be a termékeket mennyiségekkel. A korrekciós sorokat lássa el Rejtett és Fix ár beállítással.
- Az ajánlatban: Kattintson a Készlet hozzáadása gombra, válassza ki a készletet és a mennyiséget. A szakasz neve és a nyomtatási mód beillesztés előtt módosítható.
- Egyes sorok elrejtése: Az ajánlatban vagy a számlán aktiválja a Ne nyomtassa oszlopot.
- Ellenőrzés: Nyissa meg az előnézetet vagy a PDF-et. Ugyanezt a megjelenítést látják az ügyfelek a portálon.
Tesztek
A modul hat automatizált tesztet tartalmaz, amelyeket tesztadatbázison futtatunk, mielőtt bármi élesbe kerül:
- Beillesztés szakaszként, a nyomtatási móddal és az alszakasszal együtt
- Az elrejtett sor hiányzik a nyomtatandó sorok közül
- Egy sor mód (
summary) - Beillesztés szakasz nélkül, az eredeti viselkedés
- A számla átveszi a
hide_in_reportjelölést, a sor hiányzik a_get_move_lines_to_report()eredményéből, a szakaszösszeg továbbra is tartalmazza - A Csak végösszeg módú számla az elrejtett sort nem mutatja a szakaszsorokban, a szakaszösszeg teljes marad
odoo-bin -d <testdatenbank> -i sale_product_set_layout \
--test-enable --test-tags=/sale_product_set_layout --stop-after-init
A német fordítás az i18n/de.po fájlban található.
Korlátok és jogi megjegyzés
- Csak kialakítás. A modul nem változtatja meg, hogyan számolja az Odoo az árakat, a kedvezményeket vagy az adókat. Csak azt módosítja, ami nyomtatásra kerül és megjelenik a portálon.
- Az elrejtett sorok a háttérrendszerben láthatók. A jelölés a nyomtatványt és a portált érinti, nem a munkatársak képernyőnézetét.
- Ellenőrizze a számlaadatokat. Az elrejtett sorok beleszámítanak az összegbe, de nem szerepelnek a bizonylaton. Hogy ez összeegyeztethető-e az Ön országában a számlákra vonatkozó követelményekkel, például a szállított tárgyak vagy teljesített szolgáltatások előírt leírásával, azt a számlákon való használat előtt tisztázza adótanácsadójával. Az ajánlatokon az elrejtés kevésbé problémás. A cikk nem jogi tanácsadás.
- Odoo 19-re tesztelve. A modult az Odoo 19.0 Communityhez fejlesztettük és teszteltük. Olyan szakaszbeállításokat használ, amelyek ebben a formában az Odoo 19-ben léteznek. Más verziókon nem ellenőriztük.
Gyakori kérdések
Mire kell nekem a modul, ha az Odoo 19 már tud szakaszokat?
A szakaszbeállítások az Odoóban megvannak. Hiányzott a kapcsolat a termékkészlettel: a készletnek automatikusan szakaszként kellene beillesztődnie, a készletben megadott nyomtatási móddal. A modul nélkül minden beillesztés után kézzel kell létrehozni és beállítani a szakaszsort.
Miben különbözik az „Árak elrejtése” és az „Összetétel elrejtése”?
Az „Árak elrejtése” (collapse_prices) meghagyja a sorokat, de nem mutat összegeket, csak a szakasz összegét. Az „Összetétel elrejtése” (collapse_composition) teljesen elrejti a sorokat, az ügyfél csak a szakaszt látja az összeggel.
Beleszámít-e az elrejtett sor a számla összegébe?
Igen. Az elrejtett sorok megmaradnak az összegben, az adóban és a könyvelésben. A jelölés csak a nyomtatványon és az ügyfélportálon való megjelenítést érinti.
Beillesztéskor még módosíthatom a nyomtatási módot?
Igen. A mód alapértelmezésként a készletből származik, a varázslóban az adott beillesztéshez módosítható. A készlet maga ilyenkor változatlan marad.
Mi történik, ha kikapcsolom a Beillesztés szakaszként beállítást?
Ekkor a varázsló úgy viselkedik, mint az OCA sale_product_set modulban: a készlet sorai szakasz nélkül kerülnek beillesztésre.
Telepít-e a modul váratlanul további modulokat?
Maga a modul nem. Az OCA-tárolóknál azonban előfordulhatnak auto_install modulok, ha teljes tárolókat teszünk az addons_path útvonalra. Ezért csak a két szükséges modult linkelje (lásd a Telepítés című szakaszt).
Fut-e a modul az Odoo Enterprise-zal?
A modul csak Community modulokra (sale_management, account) és a két OCA-modulra épül. Mi az Odoo 19 Communityn használjuk. Enterprise-on nem teszteltük.
Milyen licenc alatt áll a modul?
Az AGPL-3 alatt. Használhatja, módosíthatja és terjesztheti, amennyiben a módosítások ugyanazon licenc alatt maradnak. A hibákat és a fejlesztési javaslatokat issue-ként szívesen fogadjuk a következő helyen: GitHub-tároló .
A Biricon IT Services támogatása
Kis- és középvállalkozások Odoo-telepítéseit gondozzuk: a bevezetéstől a testreszabásokon és migrációkon át a folyamatos üzemeltetésig. Ha a termékkészleteket, ajánlatsablonokat vagy jelentéseket az Odoo 19-ben a saját folyamataihoz szeretné igazítani, vagy ha egy ilyen modult szeretne ellenőriztetni és biztonságosan élesbe vinni, szívesen támogatjuk. További saját fejlesztéseinket blogunkban találja, például: Piszkozatszámlák összevonása és Banki fizetések automatikus hozzárendelése számlákhoz.
Állapot: 2026. november 2. Modulverzió: 19.0.1.0.0. Az ábrákon szereplő példaadatok szabadon választottak, az összegek nettó értékek.