TIP: You can type at any time to perform a new search.
Sale Order Blanket Order
sale_order_blanket_order · OCA/sale-blanket
- Repository
- OCA/sale-blanket · module folder · Try on Runboat
- Module version
- 1.0.4
- Category
- Uncategorized
- Folder size
- 0.3 MB
- License
- AGPL-3
- Application
- No
- Auto-installable
- No
- Website
- https://github.com/OCA/sale-blanket
- Last tracking update
- 2026-08-07 08:43:07
- Authors
- ACSONE SA/NV, Odoo Community Association (OCA), BCIM
- Maintainers
- ACSONE SA/NV, Odoo Community Association (OCA), BCIM
- Committers
- OCA-git-bot, oca-ci, Nicolas Delbovier, David Gallay
- Odoo dependencies
- Python dependencies
- None
- System dependencies
- None
- Required by
- sale_order_blanket_order_carrier_auto_assign, sale_order_blanket_order_stock_prebook
- Description
This module extends the functionality of Sale Order to support Blanket Order and Call-off Order. # Blanket Order A Blanket Order is a standard sales order with the following specific features: * Type: Classified as "Blanket Order". * Defined Duration: Includes a validity period (end date). * Payment Terms: Allows selection of preferred terms (e.g., 90 days end of month, upon delivery, etc.). * Invoicing Policy: Can be based on product settings or the order itself. * Stock Reservation: Allows advance reservation of sold quantities. * Handling Unfulfilled Quantities: Provides options for dealing with undelivered quantities upon order expiration. * Prices are calculated based on existing rules since it is a standard sales order type. The blanket order serves as the central element triggering stock management and invoicing mechanisms. ## Stock Management Delivered quantities are tracked on the sales order lines as with regular sales orders. By default, the stock is not reserved upon confirmation of the blanket order. This is achieved by using the OCA module [sale_manual_delivery](https://pypi.org/project/odoo-addon-sale-manual-delivery/). As a result, the stock will be reserved only when a call-off order is created for the quantity to be delivered. In some cases, you may want to reserve stock upon confirmation of the blanket order. This can be achieved by using the OCA module [sale_order_blanket_order_stock_prebook](https://pypi.org/project/odoo-addon-sale-order-blanket-order-stock-prebook/). This module extends the functionality of Sale Blanket Order to support the reservation of stock for future consumption by call-off orders. The reservation is done at the time of the blanket order confirmation for a consumption starting at the validity start date of the blanket order. This behavior can be configured on the blanket order. ## Invoicing Standard invoicing policies apply (e.g., invoice on order or on delivery). Payment terms are configurable per order. Prepayment can be enforced by configuring the invoicing policy at the order level using the OCA module [sale_invoice_policy](https://pypi.org/project/odoo-addon-sale-invoice-policy/). ## Consumption Management A wizard will be available on the blanket order to initiate a delivery. It allows users to select products and quantities for delivery. This action creates a Call-off Order linked to the blanket order. # Call-off Order A Call-off Order is a standard sales order with these specific characteristics: * Type: Classified as "Call-off Order". * Linked to Blanket Order: Only includes products from the blanket order. * Delivery Release: Enables the release of reserved stock for delivery. * No Invoicing or Stock Management: These are handled via the linked blanket order. ## Stock Management No delivery is generated directly from the call-off order. It triggers: * Release of the reserved quantity in the blanket order. * Adjustment of stock reservations for the remaining quantities. # Standard Sales Orders To support existing workflows (e.g., e-commerce), call-off orders can be generated transparently from standard sales orders based on product and availability: Entire orders may be converted into call-off orders if all products are linked to a blanket order. Mixed orders split call-off items into a new call-off order, with both confirmed within the available quantities of the blanket order.
Code Analysis ⓘ
Views touched (11)
| XML ID | Name | Model | Type | Status |
|---|---|---|---|---|
blanket_tree_view |
sale.order | tree | Inherits sale.view_order_tree | |
product_template_form_view |
product.template | form | Inherits sale.product_template_form_view | |
quotation_tree_view |
sale.order | tree | Inherits sale.view_quotation_tree | |
res_config_settings_form_view |
res.config.settings | form | Inherits sale.res_config_settings_view_form | |
sale_order_form_view |
sale.order | form | Inherits sale.view_order_form | |
sale_order_line_form_view |
sale.order.line | form | Inherits sale.sale_order_line_view_form_readonly | |
sale_order_line_search_view |
sale.order.line | search | Inherits sale.view_sales_order_line_filter | |
sale_order_line_tree_view |
sale.order.line | tree | Inherits sale.view_order_line_tree | |
sale_order_search_view |
sale.order | search | Inherits sale.view_sales_order_filter | |
sale_order_tree_view |
sale.order | tree | Inherits sale.view_order_tree | |
view_create_call_off_wizard_form |
Create Call-off Sale Order | sale.order.deliver.remaining.wizard | form | New |
HTTP endpoints (0)
No HTTP endpoints found for this module.
Models touched (9)
New fields (1)
-
allow_blanket_order_overlapBooleanhelp='If enabled, blanket orders for this product can have overlapping validityperiods. By default, overlap is not allowed, ensuring only one active blanket order applies at a time.'
No public methods.
New fields (1)
-
create_call_off_from_so_if_possibleBooleanhelp='If checked, when a sales order is confirmed and some lines refer to a blanket order, these lines will be automatically moved to a new call-off order.'string='Create Call-Off from SO if possible'
No public methods.
New fields (1)
-
create_call_off_from_so_if_possibleBooleanhelp='If checked, when a sales order is confirmed and some lines refer to a blanket order, these lines will be automatically moved to a new call-off order.'readonly=Falserelated='company_id.create_call_off_from_so_if_possible'string='Create Call-Off from SO if possible'
No public methods.
New fields (15)
-
blanket_eol_strategySelectionhelp="Specifies the end-of-life strategy for the blanket order. At the end of the validity period, in any case if a reserved quantity remains, the system will release the reservation. If the strategy is 'Deliver Remaining Quantity', the system will automaticaly create a delivery order for the remaining quantity." args: [('deliver', 'Deliver Remaining Quantity')] -
blanket_need_to_be_finalizedBooleandefault=Falsehelp='Indicates if the blanket order needs to be finalized. This field is a technical field used to manage the end-of-life of the blanket orders. To avoid costly operations to determine if the blanket order needs to be finalized once the validity period is reached, the system will set this field to True when a blanket order is confirmed. To know if a blanket order needs to be finalized, the system will search for the blanket orders with this field set to True and the validity period reached.Once the blanket order is finalized, the system will set this field to False. In this way, the DB will always contain less records to search with this field set to True.'string='Need to be Finalized' -
blanket_order_idMany2one → sale.orderhelp='The blanket order that this call-off order is related to.'index='btree_not_null'string='Blanket Order' args: 'sale.order' -
blanket_order_id_domainBinarycompute='_compute_blanket_order_id_domain'help='The domain to search for the blanket order candidates.'string='Blanket Order Domain' -
blanket_reservation_strategySelectioncompute='_compute_blanket_reservation_strategy'help="Specifies when the stock should be reserved for the blanket order. When the strategy is 'At Order Confirmation', the stock is reserved when the blanket order is confirmed. When the strategy is 'At Call-off', the stock is reserved when the call-off order is confirmed."precompute=Truereadonly=Falsestore=Truestring='Reservation Strategy' args: [('at_call_off', 'At Call-off')] -
blanket_strict_packagingBooleanhelp='If checked, the system will enforce that the products are called off with the same packaging as the one defined on the blanket order lines. If not checked, the system will not take care of the packaging defined on the blanket order lines when calling off products nor the one on the call-off order lines.'string='Strict Packaging ?'tracking=True -
blanket_validity_end_dateDatehelp='The end date of the validity period for the blanket order.'string='Validity End Date' -
blanket_validity_start_dateDatehelp='The start date of the validity period for the blanket order.'string='Validity Start Date' -
call_off_order_countIntegercompute='_compute_call_off_order_count'help='The number of call-off orders related to this blanket order.'string='Call-off Order Count' -
call_off_order_idsOne2many → sale.orderhelp='The call-off orders related to this blanket order.'string='Call-off Orders' args: 'sale.order', 'blanket_order_id' -
create_call_off_from_so_if_possibleBooleandefault=<expr>help='When this option is enabled, the system will automatically create call-off orders when a sales order is confirmed and some lines refer to a blanket order.' -
is_blanket_eol_strategy_editableBooleancompute='_compute_is_blanket_eol_strategy_editable'help='Indicates if the end-of-life strategy can be edited. By default, the end-of-life strategy can be edited while the blanket order is not finalized.' -
is_blanket_reservation_strategy_editableBooleancompute='_compute_is_blanket_reservation_strategy_editable'help='Indicates if the reservation strategy can be edited.' -
order_typeSelectiondefault='order'help='Specifies the type of sale order: Order, Blanket, or Call-off.'index=Truerequired=True args: [('order', 'Order'), ('blanket', 'Blanket Order'), ('call_off', 'Call-off Order')] -
show_deliver_remainingBooleancompute='_compute_show_deliver_remaining'help="Whether to show the 'deliver remaining' button or not"
-
action_deliver_remaining(self) -
action_view_call_off_orders(self) -
init(self) -
release_reservation(self) -
write(self, values)
New fields (2)
-
order_idMany2one → sale.orderreadonly=Truerequired=Truestring='Order' args: 'sale.order' -
wizard_line_idsOne2many → sale.order.deliver.remaining.wizard.linestring='Products to Deliver' args: 'sale.order.deliver.remaining.wizard.line', 'wizard_id'
-
action_create_call_off(self)
New fields (6)
-
call_off_remaining_qtyFloatreadonly=Truerelated='sale_order_line_id.call_off_remaining_qty'string='Remaining Quantity' -
product_idMany2one → product.productreadonly=Truerelated='sale_order_line_id.product_id'string='Product' args: 'product.product' -
product_packaging_idMany2one → product.packagingreadonly=Truerelated='sale_order_line_id.product_packaging_id'string='Packaging' args: 'product.packaging' -
qty_to_deliverFloatrequired=Truestring='Quantity to Deliver' -
sale_order_line_idMany2one → sale.order.linereadonly=Truerequired=Truestring='Sale Order Line' args: 'sale.order.line' -
wizard_idMany2one → sale.order.deliver.remaining.wizardondelete='cascade'required=Truestring='Wizard' args: 'sale.order.deliver.remaining.wizard'
No public methods.
New fields (9)
-
blanket_line_idMany2one → sale.order.linehelp='The blanket order line corresponding to this call-off order line.'index='btree_not_null'string='Blanket Order Line' args: 'sale.order.line' -
blanket_move_idsOne2many → stock.movestring='Stock Moves on Blanket Order' args: 'stock.move', 'call_off_sale_line_id' -
blanket_order_idMany2one → sale.ordercopy=Falseprecompute=Truereadonly=Truerelated='order_id.blanket_order_id'store=True args: 'sale.order' -
blanket_strict_packagingBooleancopy=Falseprecompute=Truereadonly=Truerelated='order_id.blanket_strict_packaging'store=Truestring='Strict Packaging' -
blanket_validity_end_dateDatecopy=Falseprecompute=Truereadonly=Truerelated='order_id.blanket_validity_end_date'store=Truestring='Validity End Date' -
blanket_validity_start_dateDatecopy=Falseprecompute=Truereadonly=Truerelated='order_id.blanket_validity_start_date'store=Truestring='Validity Start Date' -
call_off_line_idsOne2many → sale.order.linehelp='The call-off order lines linked to this blanket order line.'string='Call-off Order Lines' args: 'sale.order.line', 'blanket_line_id' -
call_off_remaining_qtyFloatcompute='_compute_call_off_remaining_qty'help='The quantity remaining to consume by call-off orders in case of a blanket order. This quantity is the difference between the quantity not yet delivered or part of a pending delivery and the ordered quantity.'store=Truestring='Quantity remaining for Call-off' -
order_typeSelectionprecompute=Truereadonly=Truerelated='order_id.order_type'store=True
-
init(self) -
write(self, values)
New fields (1)
-
call_off_sale_line_idMany2one → sale.order.lineindex='btree_not_null' args: 'sale.order.line', 'Call Off Sale Line'
No public methods.
New fields (0)
No new fields.
Public methods (0)No public methods.
Loading…