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,47 @@
# Supplier Calendar
Odoo addon: supplier_calendar
## Installation
```bash
pip install odoo-bringout-oca-purchase-workflow-supplier_calendar
```
## Dependencies
This addon depends on:
- purchase_stock
- resource
## Manifest Information
- **Name**: Supplier Calendar
- **Version**: 16.0.1.0.1
- **Category**: Purchase Management
- **License**: LGPL-3
- **Installable**: True
## Source
Based on [OCA/purchase-workflow](https://github.com/OCA/purchase-workflow) branch 16.0, addon `supplier_calendar`.
## 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 Supplier_calendar Module - supplier_calendar
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 supplier_calendar. 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:
- [purchase_stock](../../odoo-bringout-oca-ocb-purchase_stock)
- [resource](../../odoo-bringout-oca-ocb-resource)

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 supplier_calendar or install in UI.

View file

@ -0,0 +1,7 @@
# Install
```bash
pip install odoo-bringout-oca-purchase-workflow-supplier_calendar"
# or
uv pip install odoo-bringout-oca-purchase-workflow-supplier_calendar"
```

View file

@ -0,0 +1,15 @@
# Models
Detected core models and extensions in supplier_calendar.
```mermaid
classDiagram
class product_supplierinfo
class purchase_order_line
class res_partner
class stock_rule
```
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: supplier_calendar. Provides features documented in upstream Odoo 16 under this addon.
- Source: OCA/OCB 16.0, addon supplier_calendar
- 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 supplier_calendar
```

View file

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

View file

@ -0,0 +1,43 @@
[project]
name = "odoo-bringout-oca-purchase-workflow-supplier_calendar"
version = "16.0.0"
description = "Supplier Calendar - Supplier Calendar"
authors = [
{ name = "Ernad Husremovic", email = "hernad@bring.out.ba" }
]
dependencies = [
"odoo-bringout-oca-purchase-workflow-purchase_stock>=16.0.0",
"odoo-bringout-oca-ocb-resource>=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 = ["supplier_calendar"]
[tool.rye]
managed = true
dev-dependencies = [
"pytest>=8.4.1",
]

View file

@ -0,0 +1,116 @@
=================
Supplier Calendar
=================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:0625370e0d4f9bab63a9f026949f42ae0a4e458ad4bdc8b523c9538caabc9fed
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
:alt: License: LGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fpurchase--workflow-lightgray.png?logo=github
:target: https://github.com/OCA/purchase-workflow/tree/16.0/supplier_calendar
:alt: OCA/purchase-workflow
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/purchase-workflow-16-0/purchase-workflow-16-0-supplier_calendar
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/purchase-workflow&target_branch=16.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This module adds a Calendar to the ResPartner model. This calendar can then
used as the basis of the proper computation of start/end dates based on the
delivery lead time of the supplier in this and other modules.
In this module, the calendar is considered in the computation of the schedules
date of a stock picking and in the order date of a purchase order.
**Table of contents**
.. contents::
:local:
Configuration
=============
* Go to *Settings* and activate the developer mode.
* Go to *Settings > Technical > Resource > Working Time* and define your
resource calendar.
* Go to *Contacts > Sales&Purchases > Purchase > Delay Calendar Type*
and assign Supplier Calendar and in *Factory Closing Days* assign the
Resource Calendar desired.
Usage
=====
When a picking is created from a purchase order of a supplier, the lead
time used to calculate the scheduled date is computed in natural days. At the
same time, when a purchase order is created due to a a procurement
evaluation, its order date is also computed considering the lead time in
natural days. THis module adds the possibility of expressing the lead time
of a vendor in his own calendar. This way, the order dates of purchase
orders and the scheduled dates of receipts will only take into account the
supplier working days.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/purchase-workflow/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/purchase-workflow/issues/new?body=module:%20supplier_calendar%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* ForgeFlow
Contributors
~~~~~~~~~~~~
* Núria Martín <nuria.martin@forgeflow.com>
* Jordi Ballester <jordi.ballester@forgeflow.com>
* Lois Rilo <lois.rilo@eforgeflow>
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
.. |maintainer-LoisRForgeFlow| image:: https://github.com/LoisRForgeFlow.png?size=40px
:target: https://github.com/LoisRForgeFlow
:alt: LoisRForgeFlow
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-LoisRForgeFlow|
This module is part of the `OCA/purchase-workflow <https://github.com/OCA/purchase-workflow/tree/16.0/supplier_calendar>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View file

@ -0,0 +1,2 @@
# License LGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import models

View file

@ -0,0 +1,17 @@
# Copyright 2020 ForgeFlow
# License LGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "Supplier Calendar",
"summary": "Supplier Calendar",
"version": "16.0.1.0.1",
"website": "https://github.com/OCA/purchase-workflow",
"category": "Purchase Management",
"author": "ForgeFlow, Odoo Community Association (OCA)",
"maintainers": ["LoisRForgeFlow"],
"license": "LGPL-3",
"application": False,
"installable": True,
"auto_install": False,
"depends": ["purchase_stock", "resource"],
"data": ["views/res_partner_view.xml", "views/product_view.xml"],
}

View file

@ -0,0 +1,57 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * supplier_calendar
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \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: supplier_calendar
#: model:ir.model,name:supplier_calendar.model_res_partner
msgid "Contact"
msgstr "Kontakt"
#. module: supplier_calendar
#: model:ir.model.fields,field_description:supplier_calendar.field_product_supplierinfo__delay_calendar_type
#: model:ir.model.fields,field_description:supplier_calendar.field_res_partner__delay_calendar_type
#: model:ir.model.fields,field_description:supplier_calendar.field_res_users__delay_calendar_type
msgid "Delay Calendar Type"
msgstr "Tip kalendara kašnjenja"
#. module: supplier_calendar
#: model:ir.model.fields,field_description:supplier_calendar.field_res_partner__factory_calendar_id
#: model:ir.model.fields,field_description:supplier_calendar.field_res_users__factory_calendar_id
msgid "Factory Calendar"
msgstr "Tvorničký kalendar"
#. module: supplier_calendar
#: model:ir.model.fields.selection,name:supplier_calendar.selection__res_partner__delay_calendar_type__natural
msgid "Natural days"
msgstr "Prirodni dani"
#. module: supplier_calendar
#: model:ir.model,name:supplier_calendar.model_purchase_order_line
msgid "Purchase Order Line"
msgstr "Stavka naloga za nabavu"
#. module: supplier_calendar
#: model:ir.model,name:supplier_calendar.model_stock_rule
msgid "Stock Rule"
msgstr "Skladišno pravilo"
#. module: supplier_calendar
#: model:ir.model.fields.selection,name:supplier_calendar.selection__res_partner__delay_calendar_type__supplier_calendar
msgid "Supplier Calendar"
msgstr "Kalendar dobavljača"
#. module: supplier_calendar
#: model:ir.model,name:supplier_calendar.model_product_supplierinfo
msgid "Supplier Pricelist"
msgstr "Cjenik dobavljača"

View file

@ -0,0 +1,60 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * supplier_calendar
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-02-11 19:34+0000\n"
"Last-Translator: Ivorra78 <informatica@totmaterial.es>\n"
"Language-Team: none\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.17\n"
#. module: supplier_calendar
#: model:ir.model,name:supplier_calendar.model_res_partner
msgid "Contact"
msgstr "Contacto"
#. module: supplier_calendar
#: model:ir.model.fields,field_description:supplier_calendar.field_product_supplierinfo__delay_calendar_type
#: model:ir.model.fields,field_description:supplier_calendar.field_res_partner__delay_calendar_type
#: model:ir.model.fields,field_description:supplier_calendar.field_res_users__delay_calendar_type
msgid "Delay Calendar Type"
msgstr "Tipo de Calendario de Retraso"
#. module: supplier_calendar
#: model:ir.model.fields,field_description:supplier_calendar.field_res_partner__factory_calendar_id
#: model:ir.model.fields,field_description:supplier_calendar.field_res_users__factory_calendar_id
msgid "Factory Calendar"
msgstr "Calendario de Fábrica"
#. module: supplier_calendar
#: model:ir.model.fields.selection,name:supplier_calendar.selection__res_partner__delay_calendar_type__natural
msgid "Natural days"
msgstr "Días naturales"
#. module: supplier_calendar
#: model:ir.model,name:supplier_calendar.model_purchase_order_line
msgid "Purchase Order Line"
msgstr "Línea de Orden de Compra"
#. module: supplier_calendar
#: model:ir.model,name:supplier_calendar.model_stock_rule
msgid "Stock Rule"
msgstr "Regla de Existencias"
#. module: supplier_calendar
#: model:ir.model.fields.selection,name:supplier_calendar.selection__res_partner__delay_calendar_type__supplier_calendar
msgid "Supplier Calendar"
msgstr "Calendario de Proveedores"
#. module: supplier_calendar
#: model:ir.model,name:supplier_calendar.model_product_supplierinfo
msgid "Supplier Pricelist"
msgstr "Lista de Precios de Proveedor"

View file

@ -0,0 +1,60 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * supplier_calendar
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-01-03 10:37+0000\n"
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
"Language-Team: none\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.17\n"
#. module: supplier_calendar
#: model:ir.model,name:supplier_calendar.model_res_partner
msgid "Contact"
msgstr "Contatto"
#. module: supplier_calendar
#: model:ir.model.fields,field_description:supplier_calendar.field_product_supplierinfo__delay_calendar_type
#: model:ir.model.fields,field_description:supplier_calendar.field_res_partner__delay_calendar_type
#: model:ir.model.fields,field_description:supplier_calendar.field_res_users__delay_calendar_type
msgid "Delay Calendar Type"
msgstr "Tipo ritardo calendario"
#. module: supplier_calendar
#: model:ir.model.fields,field_description:supplier_calendar.field_res_partner__factory_calendar_id
#: model:ir.model.fields,field_description:supplier_calendar.field_res_users__factory_calendar_id
msgid "Factory Calendar"
msgstr "Calendario di fabbrica"
#. module: supplier_calendar
#: model:ir.model.fields.selection,name:supplier_calendar.selection__res_partner__delay_calendar_type__natural
msgid "Natural days"
msgstr "Giorni solari"
#. module: supplier_calendar
#: model:ir.model,name:supplier_calendar.model_purchase_order_line
msgid "Purchase Order Line"
msgstr "Riga ordine di acquisto"
#. module: supplier_calendar
#: model:ir.model,name:supplier_calendar.model_stock_rule
msgid "Stock Rule"
msgstr "Regola di giacenza"
#. module: supplier_calendar
#: model:ir.model.fields.selection,name:supplier_calendar.selection__res_partner__delay_calendar_type__supplier_calendar
msgid "Supplier Calendar"
msgstr "Calendario fornitore"
#. module: supplier_calendar
#: model:ir.model,name:supplier_calendar.model_product_supplierinfo
msgid "Supplier Pricelist"
msgstr "Listino prezzi fornitore"

View file

@ -0,0 +1,57 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * supplier_calendar
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \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: supplier_calendar
#: model:ir.model,name:supplier_calendar.model_res_partner
msgid "Contact"
msgstr ""
#. module: supplier_calendar
#: model:ir.model.fields,field_description:supplier_calendar.field_product_supplierinfo__delay_calendar_type
#: model:ir.model.fields,field_description:supplier_calendar.field_res_partner__delay_calendar_type
#: model:ir.model.fields,field_description:supplier_calendar.field_res_users__delay_calendar_type
msgid "Delay Calendar Type"
msgstr ""
#. module: supplier_calendar
#: model:ir.model.fields,field_description:supplier_calendar.field_res_partner__factory_calendar_id
#: model:ir.model.fields,field_description:supplier_calendar.field_res_users__factory_calendar_id
msgid "Factory Calendar"
msgstr ""
#. module: supplier_calendar
#: model:ir.model.fields.selection,name:supplier_calendar.selection__res_partner__delay_calendar_type__natural
msgid "Natural days"
msgstr ""
#. module: supplier_calendar
#: model:ir.model,name:supplier_calendar.model_purchase_order_line
msgid "Purchase Order Line"
msgstr ""
#. module: supplier_calendar
#: model:ir.model,name:supplier_calendar.model_stock_rule
msgid "Stock Rule"
msgstr ""
#. module: supplier_calendar
#: model:ir.model.fields.selection,name:supplier_calendar.selection__res_partner__delay_calendar_type__supplier_calendar
msgid "Supplier Calendar"
msgstr ""
#. module: supplier_calendar
#: model:ir.model,name:supplier_calendar.model_product_supplierinfo
msgid "Supplier Pricelist"
msgstr ""

View file

@ -0,0 +1,5 @@
# License LGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
from . import res_partner
from . import product
from . import stock_rule
from . import purchase

View file

@ -0,0 +1,12 @@
# Copyright 2020 ForgeFlow S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models
class ProductSupplierInfo(models.Model):
_inherit = "product.supplierinfo"
delay_calendar_type = fields.Selection(
related="partner_id.delay_calendar_type", readonly=True
)

View file

@ -0,0 +1,25 @@
# Copyright 2020 ForgeFlow S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
from datetime import datetime
from odoo import api, models
class PurchaseOrderLine(models.Model):
_inherit = "purchase.order.line"
@api.model
def _get_date_planned(self, seller, po=False):
date_planned = super(PurchaseOrderLine, self)._get_date_planned(seller, po)
if seller.partner_id.factory_calendar_id:
date_order = po.date_order if po else self.order_id.date_order
if date_order:
date_planned = seller.partner_id.supplier_plan_days(
date_order, seller.delay
)
else:
date_planned = seller.partner_id.supplier_plan_days(
datetime.today(), seller.delay
)
return date_planned

View file

@ -0,0 +1,53 @@
# Copyright 2020 ForgeFlow S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from datetime import datetime, timedelta
from odoo import api, fields, models
class ResPartner(models.Model):
_inherit = "res.partner"
factory_calendar_id = fields.Many2one(comodel_name="resource.calendar")
delay_calendar_type = fields.Selection(
[("natural", "Natural days"), ("supplier_calendar", "Supplier Calendar")],
default="natural",
required=True,
)
@api.onchange("delay_calendar_type")
def _onchange_delay_calendar_type(self):
for rec in self:
if rec.delay_calendar_type == "natural":
rec.factory_calendar_id = False
def supplier_plan_days(self, date_from, delta):
"""Helper method to calculate supplier delay based on its
working days (if set).
:param datetime date_from: reference date.
:param integer delta: delay established.
:return: datetime: resulting date.
"""
self.ensure_one()
if isinstance(delta, float):
delta = round(delta)
if not isinstance(date_from, datetime):
date_from = fields.Datetime.to_datetime(date_from)
if delta == 0:
return date_from
if self.factory_calendar_id:
if delta < 0:
# We force the date planned to be at the beginning of the day.
# So no work intervals are found in the reference date.
dt_planned = date_from.replace(hour=0)
else:
# We force the date planned at the end of the day.
dt_planned = date_from.replace(hour=23)
date_result = self.factory_calendar_id.plan_days(
delta, dt_planned, compute_leaves=True
)
else:
date_result = date_from + timedelta(days=delta)
return date_result

View file

@ -0,0 +1,24 @@
# Copyright 2020 ForgeFlow S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html)
from dateutil.relativedelta import relativedelta
from odoo import fields, models
class StockRule(models.Model):
_inherit = "stock.rule"
def _prepare_purchase_order(self, company_id, origins, values):
res = super()._prepare_purchase_order(company_id, origins, values)
dates = [fields.Datetime.from_string(value["date_planned"]) for value in values]
values = values[0]
partner = values["supplier"].partner_id
procurement_date_planned = min(dates)
schedule_date = procurement_date_planned - relativedelta(
days=company_id.po_lead
)
delay = -1 * values["supplier"].delay
purchase_date = partner.supplier_plan_days(schedule_date, delay)
res["date_order"] = purchase_date
return res

View file

@ -0,0 +1,8 @@
* Go to *Settings* and activate the developer mode.
* Go to *Settings > Technical > Resource > Working Time* and define your
resource calendar.
* Go to *Contacts > Sales&Purchases > Purchase > Delay Calendar Type*
and assign Supplier Calendar and in *Factory Closing Days* assign the
Resource Calendar desired.

View file

@ -0,0 +1,4 @@
* Núria Martín <nuria.martin@forgeflow.com>
* Jordi Ballester <jordi.ballester@forgeflow.com>
* Lois Rilo <lois.rilo@eforgeflow>

View file

@ -0,0 +1,6 @@
This module adds a Calendar to the ResPartner model. This calendar can then
used as the basis of the proper computation of start/end dates based on the
delivery lead time of the supplier in this and other modules.
In this module, the calendar is considered in the computation of the schedules
date of a stock picking and in the order date of a purchase order.

View file

@ -0,0 +1,8 @@
When a picking is created from a purchase order of a supplier, the lead
time used to calculate the scheduled date is computed in natural days. At the
same time, when a purchase order is created due to a a procurement
evaluation, its order date is also computed considering the lead time in
natural days. THis module adds the possibility of expressing the lead time
of a vendor in his own calendar. This way, the order dates of purchase
orders and the scheduled dates of receipts will only take into account the
supplier working days.

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View file

@ -0,0 +1,452 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>Supplier Calendar</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 8954 2022-01-20 10:10:25Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="supplier-calendar">
<h1 class="title">Supplier Calendar</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:0625370e0d4f9bab63a9f026949f42ae0a4e458ad4bdc8b523c9538caabc9fed
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/lgpl-3.0-standalone.html"><img alt="License: LGPL-3" src="https://img.shields.io/badge/licence-LGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/purchase-workflow/tree/16.0/supplier_calendar"><img alt="OCA/purchase-workflow" src="https://img.shields.io/badge/github-OCA%2Fpurchase--workflow-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/purchase-workflow-16-0/purchase-workflow-16-0-supplier_calendar"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/purchase-workflow&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module adds a Calendar to the ResPartner model. This calendar can then
used as the basis of the proper computation of start/end dates based on the
delivery lead time of the supplier in this and other modules.</p>
<p>In this module, the calendar is considered in the computation of the schedules
date of a stock picking and in the order date of a purchase order.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#configuration" id="toc-entry-1">Configuration</a></li>
<li><a class="reference internal" href="#usage" id="toc-entry-2">Usage</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-3">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-4">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-5">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-6">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-7">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="configuration">
<h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
<ul class="simple">
<li>Go to <em>Settings</em> and activate the developer mode.</li>
<li>Go to <em>Settings &gt; Technical &gt; Resource &gt; Working Time</em> and define your
resource calendar.</li>
<li>Go to <em>Contacts &gt; Sales&amp;Purchases &gt; Purchase &gt; Delay Calendar Type</em>
and assign Supplier Calendar and in <em>Factory Closing Days</em> assign the
Resource Calendar desired.</li>
</ul>
</div>
<div class="section" id="usage">
<h1><a class="toc-backref" href="#toc-entry-2">Usage</a></h1>
<p>When a picking is created from a purchase order of a supplier, the lead
time used to calculate the scheduled date is computed in natural days. At the
same time, when a purchase order is created due to a a procurement
evaluation, its order date is also computed considering the lead time in
natural days. THis module adds the possibility of expressing the lead time
of a vendor in his own calendar. This way, the order dates of purchase
orders and the scheduled dates of receipts will only take into account the
supplier working days.</p>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/purchase-workflow/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/purchase-workflow/issues/new?body=module:%20supplier_calendar%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#toc-entry-4">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-5">Authors</a></h2>
<ul class="simple">
<li>ForgeFlow</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
<ul class="simple">
<li>Núria Martín &lt;<a class="reference external" href="mailto:nuria.martin&#64;forgeflow.com">nuria.martin&#64;forgeflow.com</a>&gt;</li>
<li>Jordi Ballester &lt;<a class="reference external" href="mailto:jordi.ballester&#64;forgeflow.com">jordi.ballester&#64;forgeflow.com</a>&gt;</li>
<li>Lois Rilo &lt;<a class="reference external" href="mailto:lois.rilo&#64;eforgeflow">lois.rilo&#64;eforgeflow</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
<p><a class="reference external image-reference" href="https://github.com/LoisRForgeFlow"><img alt="LoisRForgeFlow" src="https://github.com/LoisRForgeFlow.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/purchase-workflow/tree/16.0/supplier_calendar">OCA/purchase-workflow</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,2 @@
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from . import test_supplier_calendar

View file

@ -0,0 +1,138 @@
# Copyright 2020 ForgeFlow S.L.
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html).
from datetime import datetime
from odoo import fields
from odoo.tests import tagged
from odoo.tests.common import TransactionCase
@tagged("post_install", "-at_install")
class TestStockWarehouseCalendar(TransactionCase):
def setUp(self):
super(TestStockWarehouseCalendar, self).setUp()
self.move_obj = self.env["stock.move"]
self.company = self.env.ref("base.main_company")
self.company_partner = self.env.ref("base.main_partner")
self.calendar = self.env.ref("resource.resource_calendar_std")
self.supplier_info = self.env["product.supplierinfo"]
self.PurchaseOrder = self.env["purchase.order"]
self.PurchaseOrderLine = self.env["purchase.order.line"]
self.stock_location = self.env.ref("stock.stock_location_stock")
self.customer_location = self.env.ref("stock.stock_location_customers")
self.picking_type_out = self.env.ref("stock.picking_type_out")
self.route_buy = self.env.ref("purchase_stock.route_warehouse0_buy").id
# Create product
self.product = self.env["product.product"].create(
{
"name": "test product",
"default_code": "PRD",
"type": "product",
"route_ids": [
(4, self.ref("stock.route_warehouse0_mto")),
(4, self.ref("purchase_stock.route_warehouse0_buy")),
],
}
)
# Partner and Supplierinfo
self.company_partner.write(
{
"delay_calendar_type": "supplier_calendar",
"factory_calendar_id": self.calendar.id,
}
)
self.seller_01 = self.supplier_info.create(
{
"partner_id": self.company_partner.id,
"product_id": self.product.id,
"product_tmpl_id": self.product.product_tmpl_id.id,
"delay": 3,
}
)
def test_01_purchase_order_with_supplier_calendar(self):
# Create a customer picking
customer_picking = self.env["stock.picking"].create(
{
"location_id": self.stock_location.id,
"location_dest_id": self.customer_location.id,
"partner_id": self.company_partner.id,
"picking_type_id": self.picking_type_out.id,
}
)
customer_move = self.env["stock.move"].create(
{
"name": "move out",
"location_id": self.stock_location.id,
"location_dest_id": self.customer_location.id,
"product_id": self.product.id,
"product_uom": self.product.uom_id.id,
"product_uom_qty": 80.0,
"procure_method": "make_to_order",
"picking_id": customer_picking.id,
"date": "2097-01-14 09:00:00", # Monday
}
)
customer_move._action_confirm()
purchase_order = self.env["purchase.order"].search(
[("partner_id", "=", self.company_partner.id)]
)
self.assertTrue(purchase_order, "No purchase order created.")
date_order = fields.Date.to_date(purchase_order.date_order)
wednesday = fields.Date.to_date("2097-01-09 09:00:00")
self.assertEqual(date_order, wednesday) # Wednesday
def test_02_purchase_order_supplier_calendar_global_leaves(self):
# Global leaves
self.calendar.write(
{
"global_leave_ids": [
(
0,
False,
{
"name": "Test",
"date_from": "2097-01-14", # Monday
"date_to": "2097-01-19", # Saturday
},
),
],
}
)
reference = "2097-01-14 09:00:00" # Monday
# With calendar
result = self.company_partner.supplier_plan_days(reference, 3).date()
next_wednesday = fields.Date.to_date("2097-01-23")
self.assertEqual(result, next_wednesday)
reference_2 = "2097-01-11 12:00:00" # friday
result = self.company_partner.supplier_plan_days(reference_2, 3).date()
self.assertEqual(result, next_wednesday)
# Without calendar
self.company_partner.write(
{"delay_calendar_type": "natural", "factory_calendar_id": False}
)
reference_3 = "2097-01-25 12:00:00" # friday
result = self.company_partner.supplier_plan_days(reference_3, 3).date()
monday = fields.Date.to_date("2097-01-28")
self.assertEqual(result, monday)
def test_03_get_seller_date_planned_from_purchase_line(self):
# We want to test the case when only the seller is provided and there is no other date.
test_date = self.company_partner.supplier_plan_days(
datetime.today(), self.seller_01.delay
)
date = self.env["purchase.order.line"]._get_date_planned(self.seller_01)
self.assertEqual(test_date, date)
def test_04_supplier_plan_days_without_delay(self):
date = fields.Date.to_date("2097-01-28")
aux_date = self.company_partner.supplier_plan_days(date, 0).date()
self.assertEqual(
date, aux_date, "The date should be the same if the delay is 0."
)

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2020 ForgeFlow S.L.
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="product_supplierinfo_form_view" model="ir.ui.view">
<field name="name">product.supplierinfo.form.view</field>
<field name="model">product.supplierinfo</field>
<field name="inherit_id" ref="product.product_supplierinfo_form_view" />
<field name="arch" type="xml">
<xpath expr="//field[@name='delay']/../../div" position="after">
<field name="delay_calendar_type" />
</xpath>
</field>
</record>
</odoo>

View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2020 ForgeFlow S.L.
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="view_partner_form" model="ir.ui.view">
<field name="name">partner.factory.calendar.form</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form" />
<field name="arch" type="xml">
<xpath
expr="//page[@name='sales_purchases']//group[@name='purchase']"
position="inside"
>
<field name="delay_calendar_type" />
<field
name='factory_calendar_id'
attrs="{'invisible': [('delay_calendar_type', '=', 'natural')]}"
/>
</xpath>
</field>
</record>
</odoo>