Initial commit: OCA Workflow Process packages (456 packages)

This commit is contained in:
Ernad Husremovic 2025-08-29 15:43:00 +02:00
commit d366e42934
18799 changed files with 1284507 additions and 0 deletions

View file

@ -0,0 +1,5 @@
# Copyright 2019 Elico Corp, Dominique K. <dominique.k@elico-corp.com.sg>
# Copyright 2019 Ecosoft Co., Ltd., Kitti U. <kittiu@ecosoft.co.th>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from . import purchase_make_invoice_advance

View file

@ -0,0 +1,246 @@
# Copyright 2019 Elico Corp, Dominique K. <dominique.k@elico-corp.com.sg>
# Copyright 2019 Ecosoft Co., Ltd., Kitti U. <kittiu@ecosoft.co.th>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import time
from datetime import datetime
from odoo import _, api, fields, models
from odoo.exceptions import UserError
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
class PurchaseAdvancePaymentInv(models.TransientModel):
_name = "purchase.advance.payment.inv"
_description = "Purchase Advance Payment Invoice"
advance_payment_method = fields.Selection(
[
("percentage", "Deposit payment (percentage)"),
("fixed", "Deposit payment (fixed amount)"),
],
string="What do you want to invoice?",
default="percentage",
required=True,
)
purchase_deposit_product_id = fields.Many2one(
comodel_name="product.product",
string="Deposit Payment Product",
domain=[("type", "=", "service")],
default=lambda self: self.env.company.purchase_deposit_product_id,
)
amount = fields.Float(
string="Deposit Payment Amount",
required=True,
help="The amount to be invoiced in advance, taxes excluded.",
)
deposit_account_id = fields.Many2one(
comodel_name="account.account",
string="Expense Account",
compute="_compute_deposit_account_id",
store=True,
readonly=False,
domain=[("deprecated", "=", False)],
help="Account used for deposits",
)
deposit_taxes_id = fields.Many2many(
comodel_name="account.tax",
string="Vendor Taxes",
compute="_compute_deposit_account_id",
store=True,
readonly=False,
help="Taxes used for deposits",
)
@api.depends("purchase_deposit_product_id")
def _compute_deposit_account_id(self):
product = self.purchase_deposit_product_id
self.deposit_account_id = product.property_account_expense_id
self.deposit_taxes_id = product.supplier_taxes_id
def _prepare_deposit_val(self, order, po_line, amount):
ir_property_obj = self.env["ir.property"]
account_id = False
product = self.purchase_deposit_product_id
if product.id:
account_id = (
product.property_account_expense_id.id
or product.categ_id.property_account_expense_categ_id.id
)
if not account_id:
inc_acc = ir_property_obj._get(
"property_account_expense_categ_id", "product.category"
)
account_id = (
order.fiscal_position_id.map_account(inc_acc).id if inc_acc else False
)
if not account_id:
raise UserError(
_(
"There is no purchase account defined for this product: %s."
"\nYou may have to install a chart of account from "
"Accounting app, settings menu."
)
% (product.name,)
)
if self.amount <= 0:
raise UserError(_("The value of the deposit must be positive."))
context = {"lang": order.partner_id.lang}
amount = self.amount
if self.advance_payment_method == "percentage": # Case percent
if self.amount > 100:
raise UserError(_("The percentage of the deposit must be not over 100"))
amount = self.amount / 100 * order.amount_untaxed
name = _("Deposit Payment")
del context
taxes = product.supplier_taxes_id.filtered(
lambda r: not order.company_id or r.company_id == order.company_id
)
if order.fiscal_position_id and taxes:
tax_ids = order.fiscal_position_id.map_tax(taxes).ids
else:
tax_ids = taxes.ids
deposit_val = {
"invoice_origin": order.name,
"move_type": "in_invoice",
"partner_id": order.partner_id.id,
"invoice_line_ids": [
(
0,
0,
{
"name": name,
"account_id": account_id,
"price_unit": amount,
"quantity": 1.0,
"product_uom_id": product.uom_id.id,
"product_id": product.id,
"purchase_line_id": po_line.id,
"tax_ids": [(6, 0, tax_ids)],
"analytic_distribution": po_line.analytic_distribution,
},
)
],
"currency_id": order.currency_id.id,
"invoice_payment_term_id": order.payment_term_id.id,
"fiscal_position_id": order.fiscal_position_id.id
or order.partner_id.property_account_position_id.id,
"purchase_id": order.id,
"narration": order.notes,
}
return deposit_val
def _create_invoice(self, order, po_line, amount):
Invoice = self.env["account.move"]
deposit_val = self._prepare_deposit_val(order, po_line, amount)
invoice = Invoice.create(deposit_val)
invoice.message_post_with_view(
"mail.message_origin_link",
values={"self": invoice, "origin": order},
subtype_id=self.env.ref("mail.mt_note").id,
)
return invoice
def _prepare_advance_purchase_line(self, order, product, tax_ids, amount):
return {
"name": _("Advance: %s") % (time.strftime("%m %Y"),),
"price_unit": amount,
"product_qty": 0.0,
"order_id": order.id,
"product_uom": product.uom_id.id,
"product_id": product.id,
"taxes_id": [(6, 0, tax_ids)],
"date_planned": datetime.today().strftime(DEFAULT_SERVER_DATETIME_FORMAT),
"is_deposit": True,
"sequence": order.order_line
and order.order_line[-1].sequence + 1
or self.env["purchase.order.line"]
.default_get(["sequence"])
.get("sequence"),
}
def _prepare_advance_purchase_section_values(self, order):
context = {"lang": order.partner_id.lang}
so_values = {
"name": _("Purchase Deposits"),
"product_qty": 0.0,
"order_id": order.id,
"display_type": "line_section",
"is_deposit": True,
"sequence": order.order_line
and order.order_line[-1].sequence + 1
or self.env["purchase.order.line"]
.default_get(["sequence"])
.get("sequence"),
}
del context
return so_values
def create_invoices(self):
Purchase = self.env["purchase.order"]
purchases = Purchase.browse(self._context.get("active_ids", []))
# Create deposit product if necessary
product = self.purchase_deposit_product_id
if not product:
vals = self._prepare_deposit_product()
product = self.purchase_deposit_product_id = (
self.env["product.product"].sudo().create(vals)
)
self.env.company.sudo().purchase_deposit_product_id = product
PurchaseLine = self.env["purchase.order.line"]
for order in purchases:
amount = self.amount
if self.advance_payment_method == "percentage": # Case percent
amount = self.amount / 100 * order.amount_untaxed
if product.purchase_method != "purchase":
raise UserError(
_(
"The product used to invoice a down payment should have "
'an invoice policy set to "Ordered quantities". '
"Please update your deposit product to be able to "
"create a deposit invoice."
)
)
if product.type != "service":
raise UserError(
_(
"The product used to invoice a down payment should be "
'of type "Service". Please use another product or '
"update this product."
)
)
taxes = product.supplier_taxes_id.filtered(
lambda r: not order.company_id or r.company_id == order.company_id
)
if order.fiscal_position_id and taxes:
tax_ids = order.fiscal_position_id.map_tax(taxes).ids
else:
tax_ids = taxes.ids
context = {"lang": order.partner_id.lang}
if not any(
line.display_type and line.is_deposit for line in order.order_line
):
PurchaseLine.create(
self._prepare_advance_purchase_section_values(order)
)
adv_po_line_dict = self._prepare_advance_purchase_line(
order, product, tax_ids, amount
)
po_line = PurchaseLine.create(adv_po_line_dict)
del context
self._create_invoice(order, po_line, amount)
if self._context.get("open_bills", False):
return purchases.action_view_invoice()
return {"type": "ir.actions.act_window_close"}
def _prepare_deposit_product(self):
return {
"name": "Purchase Deposit",
"type": "service",
"purchase_method": "purchase",
"property_account_expense_id": self.deposit_account_id.id,
"supplier_taxes_id": [(6, 0, self.deposit_taxes_id.ids)],
"company_id": False,
}

View file

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<record id="view_purchase_advance_payment_inv" model="ir.ui.view">
<field name="name">Invoice Orders</field>
<field name="model">purchase.advance.payment.inv</field>
<field name="arch" type="xml">
<form string="Invoice Purchases Order">
<p class="oe_grey">
Invoices will be created in draft so that you can review them before validation.
</p>
<group>
<field
name="advance_payment_method"
class="oe_inline"
widget="radio"
/>
<field
name="purchase_deposit_product_id"
invisible="1"
class="oe_inline"
context="{'search_default_services': 1, 'default_type': 'service', 'default_invoice_policy': 'order'}"
/>
<label for="amount" />
<div>
<field name="amount" class="oe_inline" widget="monetary" />
<span
attrs="{'invisible': [('advance_payment_method', '!=', 'percentage')]}"
class="oe_inline"
>%</span>
</div>
<field
name="deposit_account_id"
class="oe_inline"
attrs="{'invisible': [('purchase_deposit_product_id', '!=', False)]}"
/>
<field
name="deposit_taxes_id"
class="oe_inline"
widget="many2many_tags"
domain="[('type_tax_use','=','purchase')]"
attrs="{'invisible': [('purchase_deposit_product_id', '!=', False)]}"
/>
</group>
<footer>
<button
name="create_invoices"
string="Create and View bills"
type="object"
context="{'open_bills': True}"
class="btn-primary"
/>
<button
name="create_invoices"
string="Create Bill"
type="object"
class="btn-primary"
/>
<button string="Cancel" class="btn-default" special="cancel" />
</footer>
</form>
</field>
</record>
<record id="action_view_purchase_advance_payment_inv" model="ir.actions.act_window">
<field name="name">Invoice Order</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">purchase.advance.payment.inv</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</odoo>