Initial commit: Pos packages

This commit is contained in:
Ernad Husremovic 2025-08-29 15:20:50 +02:00
commit 95dfb9edb0
1301 changed files with 264148 additions and 0 deletions

View file

@ -0,0 +1,49 @@
# pos_mrp
This is a link module between Point of Sale and Mrp.
## Installation
```bash
pip install odoo-bringout-oca-ocb-pos_mrp
```
## Dependencies
This addon depends on:
- point_of_sale
- mrp
## Manifest Information
- **Name**: pos_mrp
- **Version**: 1.0
- **Category**: Hidden
- **License**: LGPL-3
- **Installable**: True
## Source
Based on [OCA/OCB](https://github.com/OCA/OCB) branch 16.0, addon `pos_mrp`.
## License
This package maintains the original LGPL-3 license from the upstream Odoo project.
## Documentation
- Overview: doc/OVERVIEW.md
- Architecture: doc/ARCHITECTURE.md
- Models: doc/MODELS.md
- Controllers: doc/CONTROLLERS.md
- Wizards: doc/WIZARDS.md
- Reports: doc/REPORTS.md
- Security: doc/SECURITY.md
- Install: doc/INSTALL.md
- Usage: doc/USAGE.md
- Configuration: doc/CONFIGURATION.md
- Dependencies: doc/DEPENDENCIES.md
- Troubleshooting: doc/TROUBLESHOOTING.md
- FAQ: doc/FAQ.md

View file

@ -0,0 +1,32 @@
# Architecture
```mermaid
flowchart TD
U[Users] -->|HTTP| V[Views and QWeb Templates]
V --> C[Controllers]
V --> W[Wizards Transient Models]
C --> M[Models and ORM]
W --> M
M --> R[Reports]
DX[Data XML] --> M
S[Security ACLs and Groups] -. enforces .-> M
subgraph Pos_mrp Module - pos_mrp
direction LR
M:::layer
W:::layer
C:::layer
V:::layer
R:::layer
S:::layer
DX:::layer
end
classDef layer fill:#eef8ff,stroke:#6ea8fe,stroke-width:1px
```
Notes
- Views include tree/form/kanban templates and report templates.
- Controllers provide website/portal routes when present.
- Wizards are UI flows implemented with `models.TransientModel`.
- Data XML loads data/demo records; Security defines groups and access.

View file

@ -0,0 +1,3 @@
# Configuration
Refer to Odoo settings for pos_mrp. Configure related models, access rights, and options as needed.

View file

@ -0,0 +1,3 @@
# Controllers
This module does not define custom HTTP controllers.

View file

@ -0,0 +1,6 @@
# Dependencies
This addon depends on:
- [point_of_sale](../../odoo-bringout-oca-ocb-point_of_sale)
- [mrp](../../odoo-bringout-oca-ocb-mrp)

View file

@ -0,0 +1,4 @@
# FAQ
- Q: Which Odoo version? A: 16.0 (OCA/OCB packaged).
- Q: How to enable? A: Start server with --addon pos_mrp or install in UI.

View file

@ -0,0 +1,7 @@
# Install
```bash
pip install odoo-bringout-oca-ocb-pos_mrp"
# or
uv pip install odoo-bringout-oca-ocb-pos_mrp"
```

View file

@ -0,0 +1,13 @@
# Models
Detected core models and extensions in pos_mrp.
```mermaid
classDiagram
class pos_order
class pos_order_line
```
Notes
- Classes show model technical names; fields omitted for brevity.
- Items listed under _inherit are extensions of existing models.

View file

@ -0,0 +1,6 @@
# Overview
Packaged Odoo addon: pos_mrp. Provides features documented in upstream Odoo 16 under this addon.
- Source: OCA/OCB 16.0, addon pos_mrp
- License: LGPL-3

View file

@ -0,0 +1,3 @@
# Reports
This module does not define custom reports.

View file

@ -0,0 +1,8 @@
# Security
This module does not define custom security rules or access controls beyond Odoo defaults.
Default Odoo security applies:
- Base user access through standard groups
- Model access inherited from dependencies
- No custom row-level security rules

View file

@ -0,0 +1,5 @@
# Troubleshooting
- Ensure Python and Odoo environment matches repo guidance.
- Check database connectivity and logs if startup fails.
- Validate that dependent addons listed in DEPENDENCIES.md are installed.

View file

@ -0,0 +1,7 @@
# Usage
Start Odoo including this addon (from repo root):
```bash
python3 scripts/nix_odoo_web_server.py --db-name mydb --addon pos_mrp
```

View file

@ -0,0 +1,3 @@
# Wizards
This module does not include UI wizards.

View file

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import models

View file

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': 'pos_mrp',
'version': '1.0',
'category': 'Hidden',
'sequence': 6,
'summary': 'Link module between Point of Sale and Mrp',
'description': """
This is a link module between Point of Sale and Mrp.
""",
'depends': ['point_of_sale', 'mrp'],
'installable': True,
'auto_install': True,
'license': 'LGPL-3',
}

View file

@ -0,0 +1,26 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * pos_mrp
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-02-06 13:31+0000\n"
"PO-Revision-Date: 2024-02-06 13:31+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: pos_mrp
#: model:ir.model,name:pos_mrp.model_pos_order_line
msgid "Point of Sale Order Lines"
msgstr "Stavke narudžbe na prodajnom mjestu"
#. module: pos_mrp
#: model:ir.model,name:pos_mrp.model_pos_order
msgid "Point of Sale Orders"
msgstr "Narudžbe POS-a"

View file

@ -0,0 +1,26 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * pos_mrp
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-02-06 13:31+0000\n"
"PO-Revision-Date: 2024-02-06 13:31+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: pos_mrp
#: model:ir.model,name:pos_mrp.model_pos_order_line
msgid "Point of Sale Order Lines"
msgstr ""
#. module: pos_mrp
#: model:ir.model,name:pos_mrp.model_pos_order
msgid "Point of Sale Orders"
msgstr ""

View file

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import pos_order

View file

@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models
class PosOrderLine(models.Model):
_inherit = "pos.order.line"
def _get_stock_moves_to_consider(self, stock_moves, product):
self.ensure_one()
bom = product.env['mrp.bom']._bom_find(product, company_id=stock_moves.company_id.id, bom_type='phantom').get(product)
if not bom:
return super()._get_stock_moves_to_consider(stock_moves, product)
boms, components = bom.explode(product, self.qty)
ml_product_to_consider = (product.bom_ids and [comp[0].product_id.id for comp in components]) or [product.id]
if len(boms) > 1:
return stock_moves.filtered(lambda ml: ml.product_id.id in ml_product_to_consider and ml.bom_line_id)
return stock_moves.filtered(lambda ml: ml.product_id.id in ml_product_to_consider and (ml.bom_line_id in bom.bom_line_ids))
class PosOrder(models.Model):
_inherit = "pos.order"
def _get_pos_anglo_saxon_price_unit(self, product, partner_id, quantity):
bom = product.env['mrp.bom']._bom_find(product, company_id=self.mapped('picking_ids.move_line_ids').company_id.id, bom_type='phantom')[product]
if not bom:
return super()._get_pos_anglo_saxon_price_unit(product, partner_id, quantity)
_dummy, components = bom.explode(product, quantity)
total_price_unit = 0
for comp in components:
price_unit = super()._get_pos_anglo_saxon_price_unit(comp[0].product_id, partner_id, comp[1]['qty'])
price_unit = comp[0].product_id.uom_id._compute_price(price_unit, comp[0].product_uom_id)
qty_per_kit = comp[1]['qty'] / bom.product_qty / quantity
total_price_unit += price_unit * qty_per_kit
return total_price_unit

View file

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import test_pos_mrp_flow

View file

@ -0,0 +1,447 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import odoo
from odoo.addons.point_of_sale.tests.common import TestPointOfSaleCommon
from odoo import fields
from odoo.tests.common import Form
@odoo.tests.tagged('post_install', '-at_install')
class TestPosMrp(TestPointOfSaleCommon):
def test_bom_kit_order_total_cost(self):
#create a product category that use fifo
category = self.env['product.category'].create({
'name': 'Category for kit',
'property_cost_method': 'fifo',
})
self.kit = self.env['product.product'].create({
'name': 'Kit Product',
'available_in_pos': True,
'type': 'product',
'lst_price': 10.0,
'categ_id': category.id,
})
self.component_a = self.env['product.product'].create({
'name': 'Comp A',
'type': 'product',
'available_in_pos': True,
'lst_price': 10.0,
'standard_price': 5.0,
})
self.component_b = self.env['product.product'].create({
'name': 'Comp B',
'type': 'product',
'available_in_pos': True,
'lst_price': 10.0,
'standard_price': 10.0,
})
bom_product_form = Form(self.env['mrp.bom'])
bom_product_form.product_id = self.kit
bom_product_form.product_tmpl_id = self.kit.product_tmpl_id
bom_product_form.product_qty = 1.0
bom_product_form.type = 'phantom'
with bom_product_form.bom_line_ids.new() as bom_line:
bom_line.product_id = self.component_a
bom_line.product_qty = 1.0
with bom_product_form.bom_line_ids.new() as bom_line:
bom_line.product_id = self.component_b
bom_line.product_qty = 1.0
self.bom_a = bom_product_form.save()
self.pos_config.open_ui()
order = self.env['pos.order'].create({
'session_id': self.pos_config.current_session_id.id,
'lines': [(0, 0, {
'name': self.kit.name,
'product_id': self.kit.id,
'price_unit': self.kit.lst_price,
'qty': 1,
'tax_ids': [[6, False, []]],
'price_subtotal': self.kit.lst_price,
'price_subtotal_incl': self.kit.lst_price,
})],
'pricelist_id': self.pos_config.pricelist_id.id,
'amount_paid': self.kit.lst_price,
'amount_total': self.kit.lst_price,
'amount_tax': 0.0,
'amount_return': 0.0,
'to_invoice': False,
})
payment_context = {"active_ids": order.ids, "active_id": order.id}
order_payment = self.PosMakePayment.with_context(**payment_context).create({
'amount': order.amount_total,
'payment_method_id': self.cash_payment_method.id
})
order_payment.with_context(**payment_context).check()
self.pos_config.current_session_id.action_pos_session_closing_control()
pos_order = self.env['pos.order'].search([], order='id desc', limit=1)
self.assertEqual(pos_order.lines[0].total_cost, 15.0)
def test_bom_kit_with_kit_invoice_valuation(self):
# create a product category that use fifo
category = self.env['product.category'].create({
'name': 'Category for kit',
'property_cost_method': 'fifo',
'property_valuation': 'real_time',
})
self.kit = self.env['product.product'].create({
'name': 'Final Kit',
'available_in_pos': True,
'categ_id': category.id,
'taxes_id': False,
'type': 'product',
})
self.kit_2 = self.env['product.product'].create({
'name': 'Final Kit 2',
'available_in_pos': True,
'categ_id': category.id,
'taxes_id': False,
'type': 'product',
})
self.subkit1 = self.env['product.product'].create({
'name': 'Subkit 1',
'available_in_pos': True,
'categ_id': category.id,
'taxes_id': False,
})
self.subkit2 = self.env['product.product'].create({
'name': 'Subkit 2',
'available_in_pos': True,
'categ_id': category.id,
'taxes_id': False,
})
self.component_a = self.env['product.product'].create({
'name': 'Comp A',
'available_in_pos': True,
'standard_price': 5.0,
'categ_id': category.id,
'taxes_id': False,
})
self.component_b = self.env['product.product'].create({
'name': 'Comp B',
'available_in_pos': True,
'standard_price': 5.0,
'categ_id': category.id,
'taxes_id': False,
})
self.component_c = self.env['product.product'].create({
'name': 'Comp C',
'available_in_pos': True,
'standard_price': 5.0,
'categ_id': category.id,
'taxes_id': False,
})
bom_product_form = Form(self.env['mrp.bom'])
bom_product_form.product_id = self.subkit1
bom_product_form.product_tmpl_id = self.subkit1.product_tmpl_id
bom_product_form.product_qty = 1.0
bom_product_form.type = 'phantom'
with bom_product_form.bom_line_ids.new() as bom_line:
bom_line.product_id = self.component_a
bom_line.product_qty = 1.0
self.bom_a = bom_product_form.save()
bom_product_form = Form(self.env['mrp.bom'])
bom_product_form.product_id = self.subkit2
bom_product_form.product_tmpl_id = self.subkit2.product_tmpl_id
bom_product_form.product_qty = 1.0
bom_product_form.type = 'phantom'
with bom_product_form.bom_line_ids.new() as bom_line:
bom_line.product_id = self.component_b
bom_line.product_qty = 1.0
with bom_product_form.bom_line_ids.new() as bom_line:
bom_line.product_id = self.component_c
bom_line.product_qty = 1.0
self.bom_b = bom_product_form.save()
bom_product_form = Form(self.env['mrp.bom'])
bom_product_form.product_id = self.kit
bom_product_form.product_tmpl_id = self.kit.product_tmpl_id
bom_product_form.product_qty = 1.0
bom_product_form.type = 'phantom'
with bom_product_form.bom_line_ids.new() as bom_line:
bom_line.product_id = self.subkit1
bom_line.product_qty = 1.0
with bom_product_form.bom_line_ids.new() as bom_line:
bom_line.product_id = self.subkit2
bom_line.product_qty = 1.0
self.final_bom = bom_product_form.save()
bom_product_form = Form(self.env['mrp.bom'])
bom_product_form.product_id = self.kit_2
bom_product_form.product_tmpl_id = self.kit_2.product_tmpl_id
bom_product_form.product_qty = 1.0
bom_product_form.type = 'phantom'
with bom_product_form.bom_line_ids.new() as bom_line:
bom_line.product_id = self.subkit1
bom_line.product_qty = 2.0
with bom_product_form.bom_line_ids.new() as bom_line:
bom_line.product_id = self.subkit2
bom_line.product_qty = 3.0
self.final_bom = bom_product_form.save()
self.pos_config.open_ui()
order_data = {'data':
{'to_invoice': True,
'amount_paid': 2.0,
'amount_return': 0,
'amount_tax': 0,
'amount_total': 2.0,
'creation_date': fields.Datetime.to_string(fields.Datetime.now()),
'fiscal_position_id': False,
'pricelist_id': self.pos_config.available_pricelist_ids[0].id,
'lines': [[0,
0,
{'discount': 0,
'pack_lot_ids': [],
'price_unit': 2,
'product_id': self.kit.id,
'price_subtotal': 2,
'price_subtotal_incl': 2,
'qty': 1,
'tax_ids': [(6, 0, self.kit.taxes_id.ids)]}],
[0,
0,
{'discount': 0,
'pack_lot_ids': [],
'price_unit': 2,
'product_id': self.kit_2.id,
'price_subtotal': 2,
'price_subtotal_incl': 2,
'qty': 1,
'tax_ids': [(6, 0, self.kit_2.taxes_id.ids)]}]],
'name': 'Order 00042-003-0014',
'partner_id': self.partner1.id,
'pos_session_id': self.pos_config.current_session_id.id,
'sequence_number': 2,
'statement_ids': [[0,
0,
{'amount': 2.0,
'name': fields.Datetime.now(),
'payment_method_id': self.cash_payment_method.id}]],
'uid': '00042-003-0014',
'user_id': self.env.uid},
}
order = self.env['pos.order'].create_from_ui([order_data])
order = self.env['pos.order'].browse(order[0]['id'])
self.assertEqual(order.lines.filtered(lambda l: l.product_id == self.kit).total_cost, 15.0)
accounts = self.kit.product_tmpl_id.get_product_accounts()
debit_interim_account = accounts['stock_output']
credit_expense_account = accounts['expense']
invoice_accounts = order.account_move.line_ids.mapped('account_id.id')
self.assertTrue(debit_interim_account.id in invoice_accounts)
self.assertTrue(credit_expense_account.id in invoice_accounts)
expense_line = order.account_move.line_ids.filtered(lambda l: l.account_id.id == credit_expense_account.id)
self.assertEqual(expense_line.filtered(lambda l: l.product_id == self.kit).credit, 0.0)
self.assertEqual(expense_line.filtered(lambda l: l.product_id == self.kit).debit, 15.0)
interim_line = order.account_move.line_ids.filtered(lambda l: l.account_id.id == debit_interim_account.id)
self.assertEqual(interim_line.filtered(lambda l: l.product_id == self.kit).credit, 15.0)
self.assertEqual(interim_line.filtered(lambda l: l.product_id == self.kit).debit, 0.0)
self.pos_config.current_session_id.action_pos_session_closing_control()
def test_bom_kit_different_uom_invoice_valuation(self):
"""This test make sure that when a kit is made of product using UoM A but the bom line uses UoM B
the price unit is correctly computed on the invoice lines.
"""
self.env.user.groups_id += self.env.ref('uom.group_uom')
category = self.env['product.category'].create({
'name': 'Category for kit',
'property_cost_method': 'fifo',
'property_valuation': 'real_time',
})
self.kit = self.env['product.product'].create({
'name': 'Final Kit',
'available_in_pos': True,
'categ_id': category.id,
'taxes_id': False,
'type': 'product',
})
self.component_a = self.env['product.product'].create({
'name': 'Comp A',
'available_in_pos': True,
'standard_price': 12000.0,
'categ_id': category.id,
'taxes_id': False,
'uom_id': self.env.ref('uom.product_uom_dozen').id,
})
bom_product_form = Form(self.env['mrp.bom'])
bom_product_form.product_id = self.kit
bom_product_form.product_tmpl_id = self.kit.product_tmpl_id
bom_product_form.product_qty = 2.0
bom_product_form.type = 'phantom'
with bom_product_form.bom_line_ids.new() as bom_line:
bom_line.product_id = self.component_a
bom_line.product_qty = 6.0
bom_line.product_uom_id = self.env.ref('uom.product_uom_unit')
self.bom_a = bom_product_form.save()
self.pos_config.open_ui()
order_data = {'data':
{'to_invoice': True,
'amount_paid': 2.0,
'amount_return': 0,
'amount_tax': 0,
'amount_total': 2.0,
'creation_date': fields.Datetime.to_string(fields.Datetime.now()),
'fiscal_position_id': False,
'pricelist_id': self.pos_config.available_pricelist_ids[0].id,
'lines': [[0,
0,
{'discount': 0,
'pack_lot_ids': [],
'price_unit': 2,
'product_id': self.kit.id,
'price_subtotal': 2,
'price_subtotal_incl': 2,
'qty': 2,
'tax_ids': []}],
],
'name': 'Order 00042-003-0014',
'partner_id': self.partner1.id,
'pos_session_id': self.pos_config.current_session_id.id,
'sequence_number': 2,
'statement_ids': [[0,
0,
{'amount': 2.0,
'name': fields.Datetime.now(),
'payment_method_id': self.cash_payment_method.id}]],
'uid': '00042-003-0014',
'user_id': self.env.uid},
}
order = self.env['pos.order'].create_from_ui([order_data])
order = self.env['pos.order'].browse(order[0]['id'])
accounts = self.kit.product_tmpl_id.get_product_accounts()
expense_line = order.account_move.line_ids.filtered(lambda l: l.account_id.id == accounts['expense'].id)
self.assertEqual(expense_line.filtered(lambda l: l.product_id == self.kit).debit, 6000.0)
interim_line = order.account_move.line_ids.filtered(lambda l: l.account_id.id == accounts['stock_output'].id)
self.assertEqual(interim_line.filtered(lambda l: l.product_id == self.kit).credit, 6000.0)
def test_bom_kit_order_total_cost_with_shared_component(self):
category = self.env['product.category'].create({
'name': 'Category for average cost',
'property_cost_method': 'average',
})
kit_1 = self.env['product.product'].create({
'name': 'Kit Product 1',
'available_in_pos': True,
'type': 'product',
'lst_price': 30.0,
'categ_id': category.id,
})
kit_2 = self.env['product.product'].create({
'name': 'Kit Product 2',
'available_in_pos': True,
'type': 'product',
'lst_price': 200.0,
'categ_id': category.id,
})
shared_component_a = self.env['product.product'].create({
'name': 'Shared Comp A',
'type': 'product',
'available_in_pos': True,
'lst_price': 10.0,
'standard_price': 5.0,
})
other_component_a = self.env['product.product'].create({
'name': 'Other Comp A',
'type': 'product',
'available_in_pos': True,
'lst_price': 20.0,
'standard_price': 10.0,
})
other_component_b = self.env['product.product'].create({
'name': 'Other Comp B',
'type': 'product',
'available_in_pos': True,
'lst_price': 30.0,
'standard_price': 20.0,
})
bom_product_form = Form(self.env['mrp.bom'])
bom_product_form.product_id = kit_1
bom_product_form.product_tmpl_id = kit_1.product_tmpl_id
bom_product_form.product_qty = 1.0
bom_product_form.type = 'phantom'
with bom_product_form.bom_line_ids.new() as bom_line:
bom_line.product_id = shared_component_a
bom_line.product_qty = 1.0
with bom_product_form.bom_line_ids.new() as bom_line:
bom_line.product_id = other_component_a
bom_line.product_qty = 1.0
self.bom_a = bom_product_form.save()
bom_product_form = Form(self.env['mrp.bom'])
bom_product_form.product_id = kit_2
bom_product_form.product_tmpl_id = kit_2.product_tmpl_id
bom_product_form.product_qty = 1.0
bom_product_form.type = 'phantom'
with bom_product_form.bom_line_ids.new() as bom_line:
bom_line.product_id = shared_component_a
bom_line.product_qty = 10.0
with bom_product_form.bom_line_ids.new() as bom_line:
bom_line.product_id = other_component_b
bom_line.product_qty = 5.0
self.bom_b = bom_product_form.save()
self.pos_config.open_ui()
order = self.env['pos.order'].create({
'session_id': self.pos_config.current_session_id.id,
'lines': [(0, 0, {
'name': kit_1.name,
'product_id': kit_1.id,
'price_unit': kit_1.lst_price,
'qty': 1,
'tax_ids': [[6, False, []]],
'price_subtotal': kit_1.lst_price,
'price_subtotal_incl': kit_1.lst_price,
}), (0, 0, {
'name': kit_2.name,
'product_id': kit_2.id,
'price_unit': kit_2.lst_price,
'qty': 1,
'tax_ids': [[6, False, []]],
'price_subtotal': kit_2.lst_price,
'price_subtotal_incl': kit_2.lst_price,
})],
'pricelist_id': self.pos_config.pricelist_id.id,
'amount_paid': kit_1.lst_price + kit_2.lst_price,
'amount_total': kit_1.lst_price + kit_2.lst_price,
'amount_tax': 0.0,
'amount_return': 0.0,
'to_invoice': False,
})
payment_context = {"active_ids": order.ids, "active_id": order.id}
order_payment = self.PosMakePayment.with_context(**payment_context).create({
'amount': order.amount_total,
'payment_method_id': self.cash_payment_method.id
})
order_payment.with_context(**payment_context).check()
self.pos_config.current_session_id.action_pos_session_closing_control()
pos_order = self.env['pos.order'].search([], order='id desc', limit=1)
self.assertRecordValues(pos_order.lines, [
{'product_id': kit_1.id, 'total_cost': 15.0},
{'product_id': kit_2.id, 'total_cost': 150.0},
])

View file

@ -0,0 +1,43 @@
[project]
name = "odoo-bringout-oca-ocb-pos_mrp"
version = "16.0.0"
description = "pos_mrp - Link module between Point of Sale and Mrp"
authors = [
{ name = "Ernad Husremovic", email = "hernad@bring.out.ba" }
]
dependencies = [
"odoo-bringout-oca-ocb-point_of_sale>=16.0.0",
"odoo-bringout-oca-ocb-mrp>=16.0.0",
"requests>=2.25.1"
]
readme = "README.md"
requires-python = ">= 3.11"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Office/Business",
]
[project.urls]
homepage = "https://github.com/bringout/0"
repository = "https://github.com/bringout/0"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.metadata]
allow-direct-references = true
[tool.hatch.build.targets.wheel]
packages = ["pos_mrp"]
[tool.rye]
managed = true
dev-dependencies = [
"pytest>=8.4.1",
]