Initial commit: Odoo 18.0-20251222 extra-addons
Some checks failed
pre-commit / pre-commit (push) Has been cancelled
tests / Detect unreleased dependencies (push) Has been cancelled
tests / test with OCB (push) Has been cancelled
tests / test with Odoo (push) Has been cancelled

This commit is contained in:
tocmo0nlord
2026-03-13 20:43:25 +00:00
parent 36e847a7df
commit adbe430761
9472 changed files with 1265727 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
from . import account_journal
from . import account_move
from . import account_chart_template

View File

@@ -0,0 +1,29 @@
# Copyright 2025 Moduon Team S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from odoo import models
from odoo.addons.account.models.chart_template import template
class AccountChartTemplate(models.AbstractModel):
_inherit = "account.chart.template"
@template(model="account.journal")
def _get_account_receipt_journal(self, template_code):
return {
"sale_receipts": {
"name": self.env._("Sale Receipts Journal"),
"code": self.env._("S-REC"),
"type": "sale",
"sequence": 99,
"receipts": True,
},
"purchase_receipts": {
"name": self.env._("Purchase Receipts Journal"),
"code": self.env._("P-REC"),
"type": "purchase",
"sequence": 99,
"receipts": True,
},
}

View File

@@ -0,0 +1,66 @@
from odoo import _, api, exceptions, fields, models
class AccountJournal(models.Model):
_inherit = "account.journal"
receipts = fields.Boolean(
string="Exclusive to Receipts",
help="If checked, this journal will be used by default for receipts "
"and only can be used for receipts.",
)
def _get_move_action_context(self):
res = super()._get_move_action_context()
ctx = self._context.copy()
journal = self or self.browse(ctx["default_journal_id"])
if not journal or not journal.receipts:
return res
if journal.type == "sale":
res["default_move_type"] = "out_receipt"
elif journal.type == "purchase":
res["default_move_type"] = "in_receipt"
return res
def open_action(self):
"""Create a new Receipt from the Dashboard
Button link in name of journal
"""
res = super().open_action()
if not self.receipts:
return res
if self.type == "sale":
res["context"]["default_move_type"] = "out_receipt"
res["domain"] = [("move_type", "=", "out_receipt")]
elif self.type == "purchase":
res["context"]["default_move_type"] = "in_receipt"
res["domain"] = [("move_type", "=", "in_receipt")]
return res
@api.constrains("sequence", "type", "receipts", "company_id")
def _check_receipts_sequence(self):
"""Ensure that journals with receipts checked, are on a higher sequence
that the rest of journals of the same type"""
for receipt_journal in self.filtered("receipts"):
journals = self.search(
[
("type", "=", receipt_journal.type),
("receipts", "=", False),
# ("sequence", "<", journal.sequence),
("id", "!=", receipt_journal.id),
("company_id", "=", receipt_journal.company_id.id),
]
)
if not journals:
continue
previous_sequence_journals = journals.filtered(
lambda j, r=receipt_journal: j.sequence < r.sequence
)
if not previous_sequence_journals:
raise exceptions.ValidationError(
_(
"The sequence of the journal '%s' must be higher than "
"the sequence of the other journals of the same type."
)
% receipt_journal.name
)

View File

@@ -0,0 +1,119 @@
from odoo import _, api, exceptions, models
class AccountMove(models.Model):
_inherit = "account.move"
@api.depends("company_id", "invoice_filter_type_domain")
def _compute_suitable_journal_ids(self):
res = super()._compute_suitable_journal_ids()
for move in self:
if move.move_type in {"in_receipt", "out_receipt"}:
move.suitable_journal_ids = move.suitable_journal_ids.filtered(
"receipts"
)
continue
move.suitable_journal_ids = move.suitable_journal_ids.filtered(
lambda x: not x.receipts
)
return res
def _search_default_receipt_journal(self, journal_types):
company_id = self.env.context.get("default_company_id", self.env.company.id)
currency_id = self.env.context.get("default_currency_id")
domain = [
("company_id", "=", company_id),
("type", "in", journal_types),
("receipts", "=", True),
]
journal = None
if currency_id:
journal = self.env["account.journal"].search(
domain + [("currency_id", "=", currency_id)], limit=1
)
if not journal:
journal = self.env["account.journal"].search(domain, limit=1)
return journal
def _search_default_journal(self):
journal = super()._search_default_journal()
# We can assume that if move_type is not in receipts, a journal without
# receipts it's coming because of the Journal constraint
if self.move_type not in {"in_receipt", "out_receipt"} or journal.receipts:
return journal
journal_types = self._get_valid_journal_types()
return self._search_default_receipt_journal(journal_types) or journal
def _get_journal_types(self, move_type):
if move_type in self.get_sale_types(include_receipts=True):
journal_types = ["sale"]
elif move_type in self.get_purchase_types(include_receipts=True):
journal_types = ["purchase"]
else:
journal_types = self.env.context.get(
"default_move_journal_types", ["general"]
)
return journal_types
@api.model
def _update_receipts_journal(self, vals_list):
"""
Update `vals_list` in place to set journal_id to the receipt journal
when move_type is receipt.
Model defaults are also considered it move_type or journal_id
are not in a `vals_list`.
"""
defaults = self.default_get(["journal_id", "move_type"])
default_journal = defaults.get("journal_id")
default_move_type = defaults.get("move_type")
for vals in vals_list:
move_type = vals.get("move_type", default_move_type)
if move_type in ("in_receipt", "out_receipt"):
selected_journal_id = vals.get("journal_id", default_journal)
selected_journal = self.env["account.journal"].browse(
selected_journal_id
)
if not selected_journal.receipts:
journal_types = self._get_journal_types(move_type)
receipt_journal = self._search_default_receipt_journal(
journal_types
)
if receipt_journal:
vals["journal_id"] = receipt_journal.id
@api.model_create_multi
def create(self, vals_list):
self._update_receipts_journal(vals_list)
return super().create(vals_list)
@api.constrains("move_type", "journal_id")
def _check_receipts_journal(self):
"""
Ensure that Receipt Journal is only used in Receipts
if exists Receipt Journals for its type
"""
aj_model = self.env["account.journal"]
receipt_domain = [("receipts", "=", True)]
has_in_rjournals = aj_model.search([("type", "=", "purchase")] + receipt_domain)
has_out_rjournals = aj_model.search([("type", "=", "sale")] + receipt_domain)
for move in self:
is_rj = move.journal_id.receipts
if move.move_type not in {"in_receipt", "out_receipt"} and is_rj:
raise exceptions.ValidationError(
_("Receipt Journal is restricted to Receipts")
)
elif move.move_type == "in_receipt" and not is_rj and has_in_rjournals:
raise exceptions.ValidationError(
_(
"Purchase Receipt must use a Receipt Journal because "
"there is already a Receipt Journal for Purchases"
)
)
elif move.move_type == "out_receipt" and not is_rj and has_out_rjournals:
raise exceptions.ValidationError(
_(
"Sale Receipt must use a Receipt Journal because "
"there is already a Receipt Journal for Sales"
)
)