Məzmuna keçin

Odoo 19 Community: təklifdə bölmə kimi məhsul dəstləri – açıq mənbəli modulumuz Sale Product Set Layout

2 noyabr 2026 | Odoo 19 Community | Öz hazırlığımız
2 noyabr 2026 tərəfindən
Odoo 19 Community: təklifdə bölmə kimi məhsul dəstləri – açıq mənbəli modulumuz Sale Product Set Layout

Odoo 19 modulu Sale Product Set Layout: təklifdə bölmə kimi məhsul dəstləri, çap rejimi, gizlədilmiş sətirlər və sabit qiymətlə

Odoo-da paketlər satan, məsələn, aksesuarlar və quraşdırma ilə birlikdə ölçü cihazı, avadanlıq və qurulma ilə iş yeri və ya bir neçə xidmətdən ibarət texniki xidmət paketi təqdim edən hər kəsin təklifdə eyni anda iki şeyə ehtiyacı var: Tərkib sifarişdə yer almalıdır ki, anbar, texniki heyət və fakturalaşdırma nəyin təhvil veriləcəyini bilsin. Lakin müştəri üçün çap versiyasında hər halda hər bir ayrı mövqe hər bir ayrı qiymətlə görünməməlidir.

OCA modulu sale_product_set məhsul dəstlərini (satış üçün spesifikasiyaları) bir kliklə təklifə əlavə etməyə imkan verir. Çap görünüşünü isə o müəyyən etmir. Bunun üçün biz Sale Product Set Layout modulunu (sale_product_set_layout) hazırladıq. O, Odoo 19 üçün yazılıb və AGPL-3 lisenziyası altında sərbəst proqram təminatı kimi GitHub-da pulsuz təqdim olunur:

github.com/Alex0176/odoo-sale-product-set-layout

Problem: çap görünüşünə təsiri olmayan məhsul dəstləri

Odoo-da məhsul dəsti miqdarları ilə birlikdə məhsulların əvvəlcədən hazırlanmış siyahısıdır. On məhsulu tək-tək axtarmaq əvəzinə, təklifdə Dəst əlavə et seçilir və bütün sətirlər bir anda əldə olunur. Bu, vaxta qənaət edir və unudulmuş mövqelərin qarşısını alır. sale_product_set modulu məhz bunu edir. Repozitoriya: OCA/sale-workflow dəstlərin özü isə product_set modulundan gəlir. Repozitoriya: OCA/product-attribute.

Təcrübədə üç boşluq qalır:

  • Tanına bilən qruplaşdırma yoxdur. Dəst sətirləri təklifdə ayrı-ayrı mövqelər kimi yerləşir. Əlavə etdikdən sonra hansı sətirlərin bir yerə aid olduğu görünmür və dəstin ümumi məbləği heç yerdə göstərilmir.
  • Çapa təsir yoxdur. Bəzən müştəri hər mövqeyi qiymətlə görməlidir, bəzən yalnız paket qiymətini, bəzən isə yalnız bir sətri. Bu, hər təklif üçün əl ilə deyil, hər dəst və ya hər müştəri üçün verilən qərardır.
  • Qiymət düzəlişləri xoşagəlməzdir. Paketin qiymət siyahısındakı məbləğlərin cəmindən fərqlənən sabit qiyməti olmalıdırsa, düzəliş sətri lazım olur. O, hesablamaya aiddir, lakin mütləq müştərinin kağızında olmalı deyil.

Odoo 19 bunu səliqəli həll etmək üçün lazımi elementləri özü ilə gətirir: bölmələr və alt bölmələr – təklif sətirlərində Qiymətləri gizlət və Tərkibi gizlət seçimləri ilə (collapse_prices və collapse_composition sahələri). Modul özünəməxsus çap formatı icad etmək əvəzinə məhsul dəstini bu standart seçimlərlə birləşdirir.

Modul nə edir

  1. Dəstin bölmə kimi əlavə edilməsi. Dəst əlavə et köməkçisi dəstin adı ilə bölmə sətri yaradır, məsələn, 2 × Messkit Standard, və dəst sətirlərini onun altına yerləşdirir. Dəstin daxilindəki bölmələr alt bölmələrə çevrilir.
  2. Hər dəst üçün çap rejimi. Dəstdə onun necə çap ediləcəyi bir dəfə müəyyən edilir. Əlavə edərkən köməkçidə rejimi həmin bir hal üçün dəyişmək olar.
  3. Sətirlərin gizlədilməsi. Ayrı-ayrı sətirlər Çap etmə (dəstdə: Gizli) kimi işarələnə bilər. Onlar cəmə daxil olur, lakin nə çap olunur, nə də müştəri portalında göstərilir. Bu işarə təklifdən qaiməyə keçir.
  4. Hər dəst sətri üçün sabit qiymət. Dəst sətri qiymət siyahısındakı qiyməti əvəz edən sabit vahid qiymət daşıya bilər, məsələn, gizlədilmiş qiymət düzəlişi üçün.
Modulsuz (yalnız sale_product_set)sale_product_set_layout ilə
Dəst sətirləri ayrı-ayrı mövqelər kimiDəstin adı ilə bölmə sətri, miqdar adda, sətirlər altında
Dəstdəki bölmələr bölmə olaraq qalır və strukturu pozurDəstdəki bölmələr alt bölmələrə çevrilir (line_subsection)
Çap görünüşü həmişə eynidirHər dəst üçün çap rejimi, əlavə edərkən dəyişdirilə bilər
Qiymət düzəlişi təklifdə və qaimədə görünürSətir gizlədilə bilər, lakin cəmə daxil olur
Qiymət yalnız qiymət siyahısındanİstəyə görə hər dəst sətri üçün sabit qiymət
Görünüş təklifdə bitirGörünüş və gizlətmə təklif, sifariş, qaimə və müştəri portalı üçün keçərlidir

Üç çap rejiminin təfərrüatları

Çap rejimi məhsul dəstindəki print_mode seçim sahəsidir. Əlavə edərkən o, bölmə sətrinin iki standart açarına çevrilir. Bunun üçün modulda yeganə, asan oxunan uyğunluq cədvəli var:

# Druckmodus -> (collapse_prices, collapse_composition) der Abschnittszeile
PRINT_MODE_FLAGS = {
    "detailed":   (False, False),
    "total_only": (True,  False),
    "summary":    (False, True),
}

Eyni məhsul dəstinin üç çap görünüşü: hər sətir qiymətlə, yalnız ümumi qiymət, yalnız bir sətir

Rejim (print_mode)Dəstdə göstərilməOdoo-da standart seçimÇap görünüşü
detailedHər sətir qiymətləyoxdurBölmə, bütün sətirlər məbləğlə
total_onlyQiymətsiz sətirlər, yalnız dəst cəmicollapse_prices (Qiymətləri gizlət)Cəmi olan bölmə, sətirlər yalnız adı və miqdarı ilə
summaryDəst cəmi ilə yalnız bir sətircollapse_composition (Tərkibi gizlət)Yalnız cəmi olan bölmə sətri

Modul özünəməxsus çap formatı deyil, Odoo 19-un standart seçimlərindən istifadə etdiyinə görə təklif, sifariş təsdiqi, qaimə və müştəri portalı uyğunlaşdırılmış hesabat şablonları olmadan işləyir. Bölmə seçimlərini nəzərə alan öz hesabat şablonları olanlar da eyni davranışı əldə edir.

Gizlədilmiş sətirlər və sabit qiymət

Tez-tez rast gəlinən hal: paketin qiyməti ayrı-ayrı qiymətlərin cəmindən aşağıdır. Ayrı-ayrı qiymətləri əymək əvəzinə sabit qiymətli düzəliş sətri götürülür (məsələn, hər dəst üçün −50,00 €) və gizlədilir. Backend-də qaimə izlənilə bilən olur, çap versiyasında isə paket qiyməti görünür.

Qiymət düzəlişi backend-də görünür və işarələnib, təklifin, PDF-in, qaimənin və portalın çap versiyasında görünmür, cəm eynidir

Başa düşmək üçün vacibdir: hide_in_report işarəsi hesablamada heç nəyi dəyişmir. Miqdar, qiymət, endirim, vergi, cəmlər və mühasibat yazıları dəyişmədən standart Odoo tərəfindən yaranır. Sətir yalnız çap versiyasında və portalda olmur.

  • Məhsul dəstində: Gizli və istəyə görə Sabit qiymət ilə birlikdə Vahid qiymət olan dəst sətri.
  • Təklif və qaimə sətirlərində: Çap etmə sütunu (hide_in_report), dəstsiz adi sətirlər üçün də.
  • Ötürülmə: Sifarişdən qaimə yaradılarkən işarə qaimə sətrinə ötürülür. Təklif kopyalananda isə qalır.

Texniki həyata keçirilmə

Modul qəsdən kiçikdir: o, mövcud modelləri genişləndirir və yalnız Odoo-nun hansı sətirlərin çap ediləcəyinə və dəstin necə əlavə ediləcəyinə qərar verdiyi yerləri üzərinə yazır. Yeni hesabat şablonları, yeni modellər və SQL müdaxilələri yoxdur.

Məlumat axını: məhsul dəsti, Dəst əlavə et köməkçisi, təklif sətirləri, qaimə sətirləri, PDF və müştəri portalı

Genişləndirilmiş modellər və sahələr

ModelƏlavə
product.setinsert_as_section (Boolean, standart olaraq aktiv) və print_mode (seçim, məcburi sahə, standart detailed) sahələri
product.set.linehide_in_report, fixed_price, price_unit sahələri; prepare_sale_order_line_values() onları təklif sətrinə ötürür
sale.product.set.wizardinsert_as_section, section_name, print_mode sahələri; _prepare_order_lines() bölmə sətrini qurur
sale.order / sale.order.linehide_in_report sahəsi (copy=True ilə); _get_order_lines_to_report() gizlədilmiş sətirləri keçir; _prepare_invoice_line() işarəni ötürür
account.move / account.move.linehide_in_report sahəsi; _get_move_lines_to_report(), _get_detailed_lines() və _get_subsection_lines() gizlədilmiş sətirləri süzgəcdən keçirir; _get_aml_vals() işarəni hesabat məlumatlarına daşıyır

Təklifdə gizlətmə

Odoo 19 çap ediləcək təklif sətirlərini _get_order_lines_to_report() metodunda müəyyən edir. Modul orada süzgəc əlavə edir. Hesabat şablonuna müdaxilə lazım deyil: həm təklifin hesabat şablonu (sale/report/ir_actions_report_templates.xml), həm də portal şablonu (sale/views/sale_portal_templates.xml) bu metodu çağırır:

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
        )

Qaiməyə ötürülmə

Qaimə sətri təklif sətrindən yaradılarkən (_prepare_invoice_line()) işarə kopyalanır. Qaimə tərəfində Odoo 19-da sətirlərin hesabata düşməsinin bir neçə yolu var: əsas siyahı, bölmənin sətirləri və alt bölmənin sətirləri. Buna görə modul bir neçə yerdə süzgəc tətbiq edir (sənəddə _get_move_lines_to_report(), sətirdə isə _get_detailed_lines() və _get_subsection_lines()), əks halda gizlədilmiş sətir digər yollardan biri ilə yenidən peyda ola bilər:

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")]

Köməkçi: ayrı-ayrı sətirlər əvəzinə bölmə

sale_product_set-dən olan sale.product.set.wizard köməkçisi təklif sətirlərini _prepare_order_lines() metodunda yaradır. Modul bu metodu üzərinə yazır. Bölmə kimi əlavə et söndürülübsə, o, sadəcə ilkin metodu çağırır, davranış OCA modulundakı kimi qalır. Əks halda əvvəlcə iki standart açarı olan bölmə sətri yaranır, ardınca dəst sətirləri gəlir. Dəstin daxilindəki bölmələr alt bölmələrə çevrilir ki, əsas strukturu pozmasınlar:

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

Görünməyən qərarlar

  • Köməkçidə ayrı hesablama metodları. Bölmə adı, çap rejimi və Bölmə kimi əlavə et üçün hər birinin öz compute metodu var (store=True, readonly=False). Üçünün hamısında eyni metod olsaydı, bir sahə üçün açıq şəkildə ötürülmüş dəyər digərlərini sıfırlayardı. Bu, əsasən köməkçi koddan və ya testlərdən dəyərlərlə yaradılanda nəzərə çarpır.
  • Miqdarlı bölmə adı. Miqdar 1-ə bərabər olmadıqda adda yazılır (2 × Messkit Standard, onluq ayırıcı olaraq vergüllə), beləliklə çap versiyasında iki dəstin olduğu, miqdarı ikiqat olan bir dəstin olmadığı bilinir.
  • Sabit qiymət yalnız məhsul sətirlərində. prepare_sale_order_line_values() hide_in_report və price_unit-i yalnız dəst sətri bölmə və ya qeyd sətri olmadıqda təyin edir.
  • Özümüz yazmaq əvəzinə standart Odoo. Çap rejimi və gizlətmə Odoo 19-un mövcud hook-larından və sahələrindən istifadə edir. Bu, yeniləmələri idarə oluna bilən edir: Odoo hesabat şablonunu dəyişsə, metodlar qaldığı müddətcə modul etibarlı qalır.

İstənilməyən yan təsirlər olmadan quraşdırma

İlkin şərtlər: Odoo 19.0, sale_product_set (OCA/sale-workflow, 19.0 branch-ı) və product_set (OCA/product-attribute, 19.0 branch-ı). Modulun özü sale_management, sale_product_set və account modullarından asılıdır.

OCA modullarında auto_install tələsi. Bir çox OCA repozitoriyasında auto_install olan modullar var. Onların asılılıqları mövcud olan kimi Odoo növbəti quraşdırma və ya yeniləmə zamanı onları soruşmadan birgə quraşdırır. Buna görə bütün OCA repozitoriyasını istehsal instansiyasının addons_path-inə qoyan hər kəs, ehtimal ki, heç kimin istəmədiyi modullar əldə edir. OCA/product-attribute üçün bu, məsələn, purchase_product_template_tags modulunə aiddir. Bizim yanaşmamız:

  1. İki OCA repozitoriyasını dayaz klonlayın (git clone --depth 1 --branch 19.0).
  2. Ayrıca qovluqda yalnız lazım olan iki modulu symlink ilə bağlayın və bütün repozitoriyaları deyil, məhz bu qovluğu addons_path-ə daxil edin.
  3. Test verilənlər bazasında quraşdırın və bu zaman hansı modulların quraşdırılmış statusu aldığını yoxlayın.
  4. Yalnız bundan sonra istehsalda quraşdırın, --workers=0 ilə, belə ki, çağırış HTTP portu uğrunda işləyən xidmətlə rəqabət aparmasın.
odoo-bin -c /etc/odoo/odoo.conf -d <datenbank> -i sale_product_set_layout --stop-after-init

Yeni sahələr və görünüşlər quraşdırıldıqdan sonra verilənlər bazasındadır. Xidmət çoxprosesli rejimdə işləyirsə, worker-lər dəyişdirilmiş registry-ni verilənlər bazası siqnalı vasitəsilə yenidən yükləyir. Modulun Python fayllarındakı dəyişikliklər isə yalnız xidmət yenidən başladıqdan sonra qüvvəyə minir.

Addım-addım istifadə

  1. Dəstin yaradılması: Satış → Məhsullar → Məhsul dəstləri. Dəstə ad verin, Bölmə kimi əlavə et və Çap rejimi seçin, məhsulları miqdarları ilə daxil edin. Düzəliş sətirlərinə Gizli və Sabit qiymət təyin edin.
  2. Təklifdə: Dəst əlavə et üzərinə klikləyin, dəsti və miqdarı seçin. Bölmə adı və çap rejimi əlavə etməzdən əvvəl dəyişdirilə bilər.
  3. Ayrı-ayrı sətirlərin gizlədilməsi: Təklifdə və ya qaimədə Çap etmə sütununu aktivləşdirin.
  4. Yoxlama: Önbaxışı və ya PDF-i açın. Müştərilər portalda eyni təsviri görür.

Testlər

Modul altı avtomatlaşdırılmış test təqdim edir, onları istehsala keçməzdən əvvəl test verilənlər bazasına qarşı icra edirik:

  • Bölmə kimi əlavə etmə, çap rejimi və alt bölmə daxil olmaqla
  • Gizlədilmiş sətir çap ediləcək sətirlərdə yoxdur
  • Bir sətir rejimi (summary)
  • Bölməsiz əlavə etmə, ilkin davranış
  • Qaimə hide_in_report işarəsini qəbul edir, sətir _get_move_lines_to_report()-də yoxdur, bölmə cəmi isə onu yenə də ehtiva edir
  • Yalnız ümumi qiymət rejimində qaimə gizli sətri bölmə sətirlərində göstərmir, bölmə cəmi isə tam qalır
odoo-bin -d <testdatenbank> -i sale_product_set_layout \
         --test-enable --test-tags=/sale_product_set_layout --stop-after-init

Alman dilində tərcümə i18n/de.po faylındadır.

Məhdudiyyətlər və hüquqi qeyd

  • Yalnız görünüş. Modul Odoo-nun qiymətləri, endirimləri və vergiləri necə hesablamasını dəyişmir. O, yalnız nəyin çap edildiyini və portalda göstərildiyini dəyişir.
  • Gizlədilmiş sətirlər backend-də görünür. İşarə çapa və portala aiddir, əməkdaşların ekran görünüşünə yox.
  • Qaimə məlumatlarını yoxlayın. Gizlədilmiş sətirlər cəmə daxil olur, lakin sənəddə yer almır. Bunun ölkənizdə qaimələrə qoyulan tələblərlə, məsələn, çatdırılmış əşyaların və ya göstərilmiş xidmətlərin məcburi təsviri ilə uyğun olub-olmadığını qaimələrdə istifadədən əvvəl vergi məsləhətçinizlə dəqiqləşdirməlisiniz. Təkliflərdə gizlətmə daha problemsizdir. Bu yazı hüquqi məsləhət deyil.
  • Odoo 19 üçün sınaqdan keçirilib. Modulu Odoo 19.0 Community üçün hazırlamış və sınaqdan keçirmişik. O, Odoo 19-da bu formada mövcud olan bölmə seçimlərindən istifadə edir. Digər versiyalar üçün yoxlamamışıq.

Tez-tez verilən suallar

Odoo 19 artıq bölmələri bacarırsa, mənə modul nə üçün lazımdır?

Bölmə seçimləri Odoo-nun özündə var. Çatışmayan məhsul dəsti ilə əlaqə idi: dəst dəstdə saxlanılmış çap rejimi ilə avtomatik olaraq bölmə kimi əlavə edilməli idi. Modul olmadan hər əlavə etmədən sonra bölmə sətrini əl ilə yaratmaq və konfiqurasiya etmək lazımdır.

“Qiymətləri gizlət” və “Tərkibi gizlət” bir-birindən nə ilə fərqlənir?

“Qiymətləri gizlət” (collapse_prices) sətirləri saxlayır, lakin məbləğləri göstərmir, yalnız bölmədəki cəmi göstərir. “Tərkibi gizlət” (collapse_composition) sətirləri tamamilə gizlədir, müştəri yalnız cəmi olan bölməni görür.

Gizlədilmiş sətir qaimə cəminə daxil olurmu?

Bəli. Gizlədilmiş sətirlər cəmdə, vergidə və mühasibat yazısında qalır. İşarə yalnız çap versiyasında və müştəri portalında təsvirə aiddir.

Əlavə edərkən çap rejimini hələ də dəyişə bilərəmmi?

Bəli. Rejim dəstdən ilkin dəyər kimi gəlir, köməkçidə isə həmin əlavə etmə üçün dəyişdirilə bilər. Dəstin özü bu zaman dəyişməz qalır.

Bölmə kimi əlavə et seçimini söndürsəm nə baş verir?

Onda köməkçi OCA modulu sale_product_set-dəki kimi davranır: dəst sətirləri bölməsiz əlavə edilir.

Modul gözlənilmədən başqa modullar quraşdırırmı?

Modulun özü yox. Lakin bütün repozitoriyaları addons_path-ə qoyduqda OCA repozitoriyalarında auto_install modulları ola bilər. Buna görə yalnız lazım olan iki modulu bağlayın (Quraşdırma bölməsinə baxın).

Modul Odoo Enterprise ilə işləyirmi?

Modul yalnız Community modullarından (sale_management, account) və iki OCA modulundan asılıdır. Biz onu Odoo 19 Community-də istifadə edirik. Enterprise-da sınaqdan keçirməmişik.

Modul hansı lisenziya altındadır?

AGPL-3 altında. Dəyişikliklər eyni lisenziya altında qaldıqca ondan istifadə edə, onu uyğunlaşdıra və yaya bilərsiniz. Xətalar və təkmilləşdirmə təklifləri Issue kimi GitHub repozitoriyası üzərində məmnuniyyətlə qəbul edilir.

Biricon IT Services dəstəyi

Biz kiçik və orta müəssisələr üçün Odoo quraşdırmalarına xidmət göstəririk: tətbiqdən uyğunlaşdırmalara və miqrasiyalara, cari istismara qədər. Odoo 19-da məhsul dəstlərini, təklif şablonlarını və ya hesabatları iş proseslərinizə uyğunlaşdırmaq istəyirsinizsə və ya bu kimi bir modulu yoxlayıb istehsal instansiyanıza təhlükəsiz gətirmək istəyirsinizsə, sizə məmnuniyyətlə dəstək oluruq. Digər öz hazırlıqlarımızı bloqumuzda tapa bilərsiniz, məsələn, Qaralama qaimələrin birləşdirilməsi və Bank ödənişlərinin qaimələrə avtomatik uyğunlaşdırılması.

İndi əlaqə saxlayın

Vəziyyət: 2 noyabr 2026. Modul versiyası 19.0.1.0.0. Təsvirlərdəki nümunə məlumatlar sərbəst seçilib, məbləğlər netto.