Repository
OCA/purchase-workflow · module folder · Try on Runboat
Module version
1.0.0
Category
Purchase Management
Folder size
1.02 MB
License
AGPL-3
Application
No
Auto-installable
No
Website
https://github.com/OCA/purchase-workflow
Last tracking update
2026-08-13 11:29:18
Authors
Odoo Community Association (OCA), AvanzOSC, Joaquín Gutierrez, Tecnativa
Maintainers
Odoo Community Association (OCA), AvanzOSC, Joaquín Gutierrez, Tecnativa
Committers
David Vidal, Weblate, OCA-git-bot, oca-ci, Andrii9090-tecnativa
Odoo dependencies
Python dependencies
None
System dependencies
None
Required by
None
Description
## This module manages your purchase expenses

The functionality of this module is to provide a way to manage your
purchase costs more easily than the official module
(*stock_landed_cost*) and allow to distribute them with a lot of
methods.

**Main features:**

- Possibility to assign landed cost afterwards in a separate screen.
- Management of expense types with preconfigured calculation methods.
- Distribution of costs based on weight, volume, product price, etc.
- Types marked as default are automatically added to each new purchase
  distribution.
- Management orders shopping expenses associated with one or more entry
  slips.

Code Analysis

Views touched (17)
XML IDNameModelTypeStatus
import_invoice_line_wizard_view import.invoice.line.wizard.form import.invoice.line.wizard form New
import_landed_cost_pickings_wizard_view import.landed.cost.pickings.wizard form New
picking_import_wizard_view picking.import.wizard.form picking.import.wizard form New
purchase_cost_distribution_form purchase.cost.distribution.form purchase.cost.distribution form New
purchase_cost_distribution_search purchase.cost.distribution.search purchase.cost.distribution search New
purchase_expense_type_tree purchase.expense.type list New
purchase_order_form purchase.order form Inherits purchase.purchase_order_form
view_move_form account.move form Inherits account.view_move_form
view_picking_form stock.picking form Inherits stock.view_picking_form
view_purchase_cost_distribution_calendar purchase.cost.distribution.calendar purchase.cost.distribution calendar New
view_purchase_cost_distribution_expense_invoice_form purchase.cost.distribution.expense list New
view_purchase_cost_distribution_graph purchase.cost.distribution.graph purchase.cost.distribution graph New
view_purchase_cost_distribution_line_expense_search purchase.cost.distribution.line.expense.search purchase.cost.distribution.line.expense search New
view_purchase_cost_distribution_line_expense_tree purchase.cost.distribution.line.expense list New
view_purchase_cost_distribution_line_form purchase.cost.distribution.line.form purchase.cost.distribution.line form New
view_purchase_cost_distribution_line_tree purchase.cost.distribution.line list New
view_purchase_cost_distribution_tree purchase.cost.distribution.tree purchase.cost.distribution list New
HTTP endpoints (0)

No HTTP endpoints found for this module.

Models touched (12)

New fields (1)
  • expense_line_ids One2many → purchase.cost.distribution.expense
    comodel_name='purchase.cost.distribution.expense' inverse_name='invoice_id' string='Landed costs'
Public methods (0)

No public methods.

New fields (1)
  • expense_line_ids One2many → purchase.cost.distribution.expense
    comodel_name='purchase.cost.distribution.expense' inverse_name='invoice_line' string='Landed costs'
Public methods (0)

No public methods.

New fields (4)
  • expense_type Many2one → purchase.expense.type
    comodel_name='purchase.expense.type' required=True string='Expense type'
  • invoice Many2one → account.move
    comodel_name='account.move' domain="[('partner_id', '=', supplier), ('move_type', '=', 'in_invoice'),('state', '=', 'posted')]" required=True
  • invoice_line Many2one → account.move.line
    comodel_name='account.move.line' domain="[('move_id', '=', invoice)]" required=True string='Invoice line'
  • supplier Many2one → res.partner
    comodel_name='res.partner' required=True
Public methods (1)
  • action_import_invoice_line(self)

New fields (2)
  • picking_ids Many2many → stock.picking
    comodel_name='stock.picking' domain="[('id', 'in', possible_picking_ids)]" relation='import_landed_cost_pickings_wizard_stock_picking_rel' string='Pickings'
  • possible_picking_ids Many2many → stock.picking
    comodel_name='stock.picking' relation='import_landed_cost_pickings_possible_picking_rel' string='Possible pickings'
Public methods (2)
  • button_import(self)
  • default_get(self, fields_list)
    @api.model

New fields (3)
  • pickings Many2many → stock.picking
    column1='wizard_id' column2='picking_id' comodel_name='stock.picking' relation='distribution_import_picking_rel' required=True string='Incoming shipments'
  • prev_pickings Many2many → stock.picking
    comodel_name='stock.picking'
  • supplier Many2one → res.partner
    comodel_name='res.partner' required=True
Public methods (2)
  • action_import_picking(self)
  • default_get(self, field_list)
    @api.model
    Get pickings previously imported.

New fields (15)
  • amount_total Float
    compute='_compute_amount_total' digits='Account' string='Total'
  • company_id Many2one → res.company
    comodel_name='res.company' default=<expr> required=True
  • cost_lines One2many → purchase.cost.distribution.line
    comodel_name='purchase.cost.distribution.line' inverse_name='distribution' string='Distribution lines'
  • currency_id Many2one → res.currency
    comodel_name='res.currency' related='company_id.currency_id' string='Currency'
  • date Date
    default=fields.Date.context_today index=True readonly=True required=True
  • expense_lines One2many → purchase.cost.distribution.expense
    comodel_name='purchase.cost.distribution.expense' default=<expr> inverse_name='distribution' string='Expenses'
  • name Char
    default='/' index=True required=True string='Distribution number'
  • note Text
    string='Documentation for this order'
  • state Selection
    default='draft' readonly=True string='Status' args: [('draft', 'Draft'), ('calculated', 'Calculated'), ('done', 'Done')]
  • total_expense Float
    compute='_compute_total_expense' digits='Account' string='Total expenses'
  • total_price_unit Float
    compute='_compute_total_price_unit' digits='Product Price' string='Total price unit'
  • total_purchase Float
    compute='_compute_total_purchase' digits='Account' string='Total purchase'
  • total_uom_qty Float
    compute='_compute_total_uom_qty' digits='Product UoS' readonly=True string='Total quantity'
  • total_volume Float
    compute='_compute_total_volume' readonly=True string='Total volume'
  • total_weight Float
    compute='_compute_total_weight' digits='Stock Weight' readonly=True string='Total gross weight'
Public methods (5)
  • action_calculate(self)
  • action_done(self)
  • action_draft(self)
  • create(self, vals_list)
    @api.model_create_multi
  • write(self, vals)

New fields (11)
  • affected_lines Many2many → purchase.cost.distribution.line
    column1='expense_id' column2='line_id' comodel_name='purchase.cost.distribution.line' domain="[('id', 'in', imported_lines)]" help='Put here specific lines that this expense is going to be distributed across. Leave it blank to use all imported lines.' relation='distribution_expense_aff_rel' string='Affected lines'
  • calculation_method Selection
    readonly=True related='type.calculation_method' string='Calculation method'
  • company_id Many2one → res.company
    comodel_name='res.company' related='distribution.company_id' store=True
  • display_name Char
    compute='_compute_display_name' store=True
  • distribution Many2one → purchase.cost.distribution
    comodel_name='purchase.cost.distribution' index=True ondelete='cascade' required=True string='Cost distribution'
  • expense_amount Float
    digits='Account' required=True string='Expense amount'
  • imported_lines Many2many → purchase.cost.distribution.line
    comodel_name='purchase.cost.distribution.line' compute='_compute_imported_lines' string='Imported lines'
  • invoice_id Many2one → account.move
    comodel_name='account.move'
  • invoice_line Many2one → account.move.line
    comodel_name='account.move.line' domain="[('move_id.move_type', '=', 'in_invoice'),('move_id.state', '=', 'posted')]" string='Supplier invoice line'
  • ref Char
    string='Reference'
  • type Many2one → purchase.expense.type
    comodel_name='purchase.expense.type' index=True ondelete='restrict' string='Expense type'
Public methods (3)
  • button_duplicate(self)
  • onchange_invoice_line(self)
    @api.onchange('invoice_line')
    set expense_amount in the currency of the distribution
  • onchange_type(self)
    @api.onchange('type')
    set expense_amount in the currency of the distribution

New fields (22)
  • company_id Many2one → res.company
    comodel_name='res.company' related='distribution.company_id' store=True
  • cost_ratio Float
    compute='_compute_cost_ratio' string='Unit cost'
  • distribution Many2one → purchase.cost.distribution
    comodel_name='purchase.cost.distribution' ondelete='cascade' required=True string='Cost distribution'
  • expense_amount Float
    compute='_compute_expense_amount' digits='Account' string='Cost amount'
  • expense_lines One2many → purchase.cost.distribution.line.expense
    comodel_name='purchase.cost.distribution.line.expense' inverse_name='distribution_line' string='Expenses distribution lines'
  • move_id Many2one → stock.move
    comodel_name='stock.move' ondelete='restrict' required=True string='Picking line'
  • name Char
    compute='_compute_name' store=True
  • partner Many2one → res.partner
    comodel_name='res.partner' readonly=True related='move_id.purchase_line_id.order_id.partner_id' string='Supplier'
  • picking_id Many2one → stock.picking
    related='move_id.picking_id' store=True string='Picking' args: 'stock.picking'
  • product_id Many2one → product.product
    comodel_name='product.product' compute='_compute_product_id' store=True
  • product_price_unit Float
    related='move_id.price_unit' string='Unit price'
  • product_qty Float
    compute='_compute_product_qty' store=True string='Quantity'
  • product_uom Many2one → uom.uom
    comodel_name='uom.uom' related='move_id.product_uom' string='Unit of measure'
  • product_volume Float
    help='The volume in m3.' related='product_id.product_tmpl_id.volume' string='Volume'
  • product_weight Float
    help='The gross weight in Kg.' related='product_id.product_tmpl_id.weight' string='Gross weight'
  • purchase_id Many2one → purchase.order
    comodel_name='purchase.order' readonly=True related='move_id.purchase_line_id.order_id' store=True string='Purchase order'
  • purchase_line_id Many2one → purchase.order.line
    comodel_name='purchase.order.line' related='move_id.purchase_line_id' string='Purchase order line'
  • standard_price_new Float
    compute='_compute_standard_price_new' digits='Product Price' string='New cost'
  • standard_price_old Float
    compute='_compute_standard_price_old' digits='Product Price' store=True string='Previous cost'
  • total_amount Float
    compute='_compute_total_amount' digits='Account' string='Amount line'
  • total_volume Float
    compute='_compute_total_volume' help='The line volume in m3.' store=True string='Line volume'
  • total_weight Float
    compute='_compute_total_weight' digits='Stock Weight' help='The line gross weight in Kg.' store=True string='Line weight'
Public methods (1)
  • get_action_purchase_cost_distribution(self)
    @api.model

New fields (8)
  • company_id Many2one → res.company
    comodel_name='res.company' readonly=True related='distribution_line.company_id' store=True
  • cost_ratio Float
    args: 'Unit cost'
  • distribution_expense Many2one → purchase.cost.distribution.expense
    comodel_name='purchase.cost.distribution.expense' ondelete='cascade' string='Distribution expense'
  • distribution_line Many2one → purchase.cost.distribution.line
    comodel_name='purchase.cost.distribution.line' ondelete='cascade' string='Cost distribution line'
  • expense_amount Float
    digits='Account' string='Expense amount'
  • picking_date_done Datetime
    readonly=True related='picking_id.date_done' store=True
  • picking_id Many2one → stock.picking
    comodel_name='stock.picking' readonly=True related='distribution_line.picking_id' store=True
  • type Many2one → purchase.expense.type
    readonly=True related='distribution_expense.type' store=True string='Expense type' args: 'purchase.expense.type'
Public methods (0)

No public methods.

New fields (6)
  • calculation_method Selection
    default='amount' string='Calculation method' args: [('amount', 'By amount of the line'), ('price', 'By product price'), ('qty', 'By product quantity'), ('weight', 'By product weight'), ('volume', 'By product volume'), ('equal', 'Equally to all lines')]
  • company_id Many2one → res.company
    comodel_name='res.company' default=<expr>
  • default_amount Float
    help='If set, this amount is put in the expense line when you select this expense type' string='Default amount'
  • default_expense Boolean
    help='Specify if the expense will be automatically added in a purchase cost distribution.'
  • name Char
    index='trigram' required=True translate=True
  • note Text
    string='Cost documentation'
Public methods (0)

No public methods.

New fields (0)

No new fields.

Public methods (1)
  • action_open_landed_cost(self)

New fields (0)

No new fields.

Public methods (1)
  • action_open_landed_cost(self)

Loading…

Loading…

Loading…

Loading…

Loading…