|
| 1 | +# Copyright 2025 Quartile (https://www.quartile.co) |
| 2 | +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). |
| 3 | + |
| 4 | +from collections import OrderedDict |
| 5 | + |
| 6 | +from odoo import _, http |
| 7 | +from odoo.exceptions import AccessError, MissingError |
| 8 | +from odoo.http import request |
| 9 | + |
| 10 | +from odoo.addons.portal.controllers.portal import CustomerPortal, pager as portal_pager |
| 11 | + |
| 12 | + |
| 13 | +class CustomerPortalBilling(CustomerPortal): |
| 14 | + def _show_report(self, model, report_type, report_ref, download=False): |
| 15 | + if model._name != "account.billing": |
| 16 | + return super()._show_report(model, report_type, report_ref, download) |
| 17 | + template = model.company_id.billing_email_template_id or request.env.ref( |
| 18 | + "account_billing_portal.email_template_billing", raise_if_not_found=False |
| 19 | + ) |
| 20 | + report = template.sudo().report_template if template else None |
| 21 | + if report: |
| 22 | + report_ref = report.id |
| 23 | + return super()._show_report(model, report_type, report_ref, download) |
| 24 | + |
| 25 | + def _get_billing_domain(self, bill_type=None): |
| 26 | + domain = [("state", "=", "billed")] |
| 27 | + if bill_type: |
| 28 | + domain.append(("bill_type", "=", bill_type)) |
| 29 | + return domain |
| 30 | + |
| 31 | + def _prepare_home_portal_values(self, counters): |
| 32 | + values = super()._prepare_home_portal_values(counters) |
| 33 | + Billing = request.env["account.billing"] |
| 34 | + if "customer_bill_count" in counters: |
| 35 | + values["customer_bill_count"] = ( |
| 36 | + Billing.search_count(self._get_billing_domain("out_invoice")) |
| 37 | + if Billing.check_access_rights("read", raise_exception=False) |
| 38 | + else 0 |
| 39 | + ) |
| 40 | + if "vendor_bill_count" in counters: |
| 41 | + values["vendor_bill_count"] = ( |
| 42 | + Billing.search_count(self._get_billing_domain("in_invoice")) |
| 43 | + if Billing.check_access_rights("read", raise_exception=False) |
| 44 | + else 0 |
| 45 | + ) |
| 46 | + return values |
| 47 | + |
| 48 | + def _get_billing_searchbar_sortings(self): |
| 49 | + return { |
| 50 | + "newest": {"label": _("Newest"), "order": "create_date desc, id desc"}, |
| 51 | + "billing_date": {"label": _("Billing Date"), "order": "date desc, id desc"}, |
| 52 | + "name": {"label": _("Name"), "order": "name asc, id asc"}, |
| 53 | + } |
| 54 | + |
| 55 | + def _render_billing_portal( |
| 56 | + self, |
| 57 | + page, |
| 58 | + sortby, |
| 59 | + filterby, |
| 60 | + searchbar_filters, |
| 61 | + default_filter, |
| 62 | + ): |
| 63 | + values = self._prepare_portal_layout_values() |
| 64 | + Billing = request.env["account.billing"] |
| 65 | + domain = self._get_billing_domain() |
| 66 | + searchbar_sortings = self._get_billing_searchbar_sortings() |
| 67 | + if not sortby: |
| 68 | + sortby = "newest" |
| 69 | + order = searchbar_sortings[sortby]["order"] |
| 70 | + if searchbar_filters: |
| 71 | + if not filterby or filterby not in searchbar_filters: |
| 72 | + filterby = default_filter |
| 73 | + domain += searchbar_filters[filterby]["domain"] |
| 74 | + count = Billing.search_count(domain) |
| 75 | + pager = portal_pager( |
| 76 | + url="/my/billings", |
| 77 | + url_args={"sortby": sortby, "filterby": filterby}, |
| 78 | + total=count, |
| 79 | + page=page, |
| 80 | + step=self._items_per_page, |
| 81 | + ) |
| 82 | + billings = Billing.search( |
| 83 | + domain, order=order, limit=self._items_per_page, offset=pager["offset"] |
| 84 | + ) |
| 85 | + request.session["my_billing_history"] = billings.ids[:100] |
| 86 | + values.update( |
| 87 | + { |
| 88 | + "billings": billings, |
| 89 | + "page_name": "billing", |
| 90 | + "pager": pager, |
| 91 | + "searchbar_sortings": searchbar_sortings, |
| 92 | + "sortby": sortby, |
| 93 | + "searchbar_filters": OrderedDict(sorted(searchbar_filters.items())), |
| 94 | + "filterby": filterby, |
| 95 | + "default_url": "/my/billings", |
| 96 | + } |
| 97 | + ) |
| 98 | + return request.render("account_billing_portal.portal_my_billings", values) |
| 99 | + |
| 100 | + @http.route( |
| 101 | + ["/my/billings", "/my/billings/page/<int:page>"], |
| 102 | + type="http", |
| 103 | + auth="user", |
| 104 | + website=True, |
| 105 | + ) |
| 106 | + def portal_my_billings(self, page=1, sortby=None, filterby=None, **kw): |
| 107 | + return self._render_billing_portal( |
| 108 | + page, |
| 109 | + sortby, |
| 110 | + filterby, |
| 111 | + { |
| 112 | + "all": { |
| 113 | + "label": _("All"), |
| 114 | + "domain": [], |
| 115 | + }, |
| 116 | + "out_invoice": { |
| 117 | + "label": _("Customer Bills"), |
| 118 | + "domain": [("bill_type", "=", "out_invoice")], |
| 119 | + }, |
| 120 | + "in_invoice": { |
| 121 | + "label": _("Vendor Bills"), |
| 122 | + "domain": [("bill_type", "=", "in_invoice")], |
| 123 | + }, |
| 124 | + }, |
| 125 | + "all", |
| 126 | + ) |
| 127 | + |
| 128 | + def _billing_get_page_view_values(self, billing, access_token, **kwargs): |
| 129 | + values = { |
| 130 | + "billing": billing, |
| 131 | + "page_name": "billing", |
| 132 | + "report_type": "html", |
| 133 | + } |
| 134 | + return self._get_page_view_values( |
| 135 | + billing, access_token, values, "my_billing_history", False, **kwargs |
| 136 | + ) |
| 137 | + |
| 138 | + @http.route( |
| 139 | + ["/my/billings/<int:billing_id>"], type="http", auth="public", website=True |
| 140 | + ) |
| 141 | + def portal_my_billing( |
| 142 | + self, billing_id, access_token=None, report_type=None, download=False, **kw |
| 143 | + ): |
| 144 | + try: |
| 145 | + billing_sudo = self._document_check_access( |
| 146 | + "account.billing", billing_id, access_token |
| 147 | + ) |
| 148 | + except (AccessError, MissingError): |
| 149 | + return request.redirect("/my") |
| 150 | + if report_type in ("html", "pdf", "text"): |
| 151 | + pdf_report_name = "account_billing.report_account_billing" |
| 152 | + return self._show_report( |
| 153 | + model=billing_sudo, |
| 154 | + report_type=report_type, |
| 155 | + report_ref=pdf_report_name, |
| 156 | + download=download, |
| 157 | + ) |
| 158 | + values = self._billing_get_page_view_values(billing_sudo, access_token, **kw) |
| 159 | + return request.render("account_billing_portal.portal_my_billing", values) |
0 commit comments