first commit

This commit is contained in:
root
2026-03-14 09:42:12 +00:00
commit 0adbd20c2c
10991 changed files with 1646955 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.

View File

@@ -0,0 +1,34 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr "Request Productions"
#, fuzzy
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr "Управление на производство"
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr ""
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr ""
#, fuzzy
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr "Управление на производство"

View File

@@ -0,0 +1,32 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr "Període de subministre"
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr "Període de subministre"
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr "Sol·licituds de producció"
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr "Producció"
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr "Hi ha algunes produccions endarrerides."
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr "Configuració del període de subministre de la producció"
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr "Producció"

View File

@@ -0,0 +1,33 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr "Request Productions"
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr "Production"
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr ""
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr ""
#, fuzzy
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr "Production"

View File

@@ -0,0 +1,32 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr "Beschaffungszeitraum"
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr "Beschaffungszeitraum"
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr "Produktionsaufträge anfordern"
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr "Produktion"
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr "Einige Produktionsaufträge sind verspätet."
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr "Einstellungen Produktion Beschaffungszeitraum"
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr "Produktion"

View File

@@ -0,0 +1,32 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr "Periodo de suministro"
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr "Periodo de suministro"
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr "Solicitudes de producción"
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr "Producción"
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr "Hay algunas producciones retrasadas."
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr "Configuración del periodo de subministro de la producción"
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr "Producción"

View File

@@ -0,0 +1,32 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr ""
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr ""
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr ""
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr ""
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr ""

View File

@@ -0,0 +1,33 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr "Tarneaeg"
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr "Tarneaeg"
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr "Tootmiste päring"
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr "Tootmine"
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr "Osad tooted hilinevad."
#, fuzzy
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr "Tootmise seadistus tarneaeg"
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr "Tootmine"

View File

@@ -0,0 +1,33 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr "دوره عرضه"
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr "دوره عرضه"
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr "درخواست تولیدات"
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr "تولید"
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr "برخی از محصولات تأخیر دارند."
#, fuzzy
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr "پیکربندی تولید ؛ دوره عرضه"
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr "تولید"

View File

@@ -0,0 +1,33 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr "Request Productions"
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr "Production"
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr ""
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr ""
#, fuzzy
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr "Production"

View File

@@ -0,0 +1,32 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr "Période d'approvisionnement"
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr "Période d'approvisionnement"
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr "Demandes de production"
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr "Production"
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr "Il y a des productions qui sont en retard."
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr "Configuration de la période d'approvisionnement de production"
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr "Production"

View File

@@ -0,0 +1,35 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr "Beszerzési időszak"
#, fuzzy
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr "Beszerzési időszak"
#, fuzzy
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr "Request Productions"
#, fuzzy
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr "Production"
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr ""
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr ""
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr "Termelés"

View File

@@ -0,0 +1,33 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr ""
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr "Produksi"
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr "Ada beberapa produksi yang terlambat."
#, fuzzy
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr "Periode Pasokan Konfigurasi Produksi"
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr "Produksi"

View File

@@ -0,0 +1,32 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr "Periodo di fornitura"
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr "Periodo di fornitura"
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr "Request Productions"
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr "Production"
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr "Ci sono alcune produzioni che sono in ritardo."
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr ""
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr "Produzione"

View File

@@ -0,0 +1,35 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr "ໄລຍະສະໜອງ"
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr "ໄລຍະສະໜອງ"
#, fuzzy
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr "Request Productions"
#, fuzzy
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr "Production"
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr ""
#, fuzzy
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr "ໄລຍະກຳນົດການສະໜອງຜະລິດຕະພັນ"
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr "ການຜະລິດ"

View File

@@ -0,0 +1,33 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr "Request Productions"
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr "Production"
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr ""
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr ""
#, fuzzy
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr "Production"

View File

@@ -0,0 +1,32 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr "Leveringstermijn"
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr "Leveringstermijn"
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr "Vraag productie aan"
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr "Productie"
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr "Er zijn enkele producties die laat zijn."
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr "Productie configuratie leveringsperiode"
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr "Productie"

View File

@@ -0,0 +1,33 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr "Request Productions"
#, fuzzy
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr "Production"
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr ""
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr ""
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr "Produkcja"

View File

@@ -0,0 +1,32 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr "Período de Abastecimento"
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr "Período de Abastecimento"
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr "Solicitar Produções"
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr "Produção"
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr "Algumas produções estão atrasadas."
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr "Configurações do Período de Abastecimento na Produção"
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr "Produção"

View File

@@ -0,0 +1,32 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr ""
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr ""
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr ""
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr ""
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr ""

View File

@@ -0,0 +1,34 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr "Request Productions"
#, fuzzy
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr "Производство"
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr ""
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr ""
#, fuzzy
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr "Производство"

View File

@@ -0,0 +1,35 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr "Obdobje dobave"
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr "Obdobje dobave"
#, fuzzy
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr "Request Productions"
#, fuzzy
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr "Production"
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr ""
#, fuzzy
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr "Konfiguracija obdobja dobave proizvodnje"
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr "Proizvodni nalog"

View File

@@ -0,0 +1,33 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr "Request Productions"
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr "Production"
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr ""
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr ""
#, fuzzy
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr "Production"

View File

@@ -0,0 +1,32 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr ""
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr ""
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr ""
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr ""
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr ""

View File

@@ -0,0 +1,33 @@
#
msgid ""
msgstr "Content-Type: text/plain; charset=utf-8\n"
msgctxt "field:production.configuration,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "field:production.configuration.supply_period,supply_period:"
msgid "Supply Period"
msgstr ""
msgctxt "model:ir.action,name:act_production_request"
msgid "Request Productions"
msgstr "Request Productions"
msgctxt ""
"model:ir.action.act_window.domain,name:act_order_point_form_domain_production"
msgid "Production"
msgstr "Production"
msgctxt "model:ir.message,text:msg_late_productions"
msgid "There are some productions that are late."
msgstr ""
msgctxt "model:production.configuration.supply_period,string:"
msgid "Production Configuration Supply Period"
msgstr ""
#, fuzzy
msgctxt "selection:stock.order_point,type:"
msgid "Production"
msgstr "Production"

View File

@@ -0,0 +1,10 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tryton>
<data grouped="1">
<record model="ir.message" id="msg_late_productions">
<field name="text">There are some productions that are late.</field>
</record>
</data>
</tryton>

View File

@@ -0,0 +1,15 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from datetime import timedelta
from trytond.pool import Pool, PoolMeta
class Product(metaclass=PoolMeta):
__name__ = 'product.product'
def get_supply_period(self):
'Return the supply period for the product'
pool = Pool()
Configuration = pool.get('production.configuration')
return Configuration(1).supply_period or timedelta(0)

View File

@@ -0,0 +1,258 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
import datetime
from collections import defaultdict
from trytond.model import ModelSQL, ValueMixin, fields
from trytond.pool import Pool, PoolMeta
from trytond.pyson import TimeDelta
from trytond.tools import grouped_slice
from trytond.transaction import Transaction
supply_period = fields.TimeDelta(
"Supply Period",
domain=['OR',
('supply_period', '=', None),
('supply_period', '>=', TimeDelta()),
])
class Configuration(metaclass=PoolMeta):
__name__ = 'production.configuration'
supply_period = fields.MultiValue(supply_period)
class ConfigurationSupplyPeriod(ModelSQL, ValueMixin):
__name__ = 'production.configuration.supply_period'
supply_period = supply_period
class Production(metaclass=PoolMeta):
__name__ = 'production'
@classmethod
def _get_origin(cls):
origins = super()._get_origin()
return origins | {'stock.order_point'}
@classmethod
def generate_requests(cls, clean=True, warehouses=None):
"""
For each product compute the production request that must be created
today to meet product outputs.
If clean is set, it will remove all previous requests.
If warehouses is specified it will compute the production requests
only for the selected warehouses.
"""
pool = Pool()
Product = pool.get('product.product')
Location = pool.get('stock.location')
Date = pool.get('ir.date')
User = pool.get('res.user')
company = User(Transaction().user).company
if not company:
return
if clean:
reqs = cls.search([
('state', '=', 'request'),
('company', '=', company.id),
('origin', 'like', 'stock.order_point,%'),
])
if warehouses:
reqs = [r for r in reqs if r.warehouse in warehouses]
cls.delete(reqs)
if not warehouses:
# fetch warehouse
warehouses = Location.search([
('type', '=', 'warehouse'),
])
warehouse_ids = [w.id for w in warehouses]
# fetch goods
products = Product.search([
('type', '=', 'goods'),
('consumable', '=', False),
('producible', '=', True),
])
# compute requests
today = Date.today()
# aggregate product by supply period
date2products = defaultdict(list)
for product in products:
min_date = today
max_date = today + product.get_supply_period()
date2products[min_date, max_date].append(product)
requests = []
for (min_date, max_date), dates_products in date2products.items():
for sub_products in grouped_slice(products):
sub_products = Product.browse(sub_products)
product2ops = {}
product2ops_other = {}
for product in sub_products:
for order_point in product.order_points:
if (order_point.company != company
or not order_point.warehouse_location):
continue
if order_point.type == 'production':
dict_ = product2ops
else:
dict_ = product2ops_other
dict_[
(order_point.warehouse_location.id,
order_point.product.id)
] = order_point
product_ids = [p.id for p in sub_products]
with Transaction().set_context(
forecast=True,
stock_date_end=min_date):
pbl = Product.products_by_location(
warehouse_ids,
with_childs=True,
grouping_filter=(product_ids,))
for warehouse in warehouses:
min_date_qties = defaultdict(int,
((x, pbl.pop((warehouse.id, x), 0))
for x in product_ids))
# Do not compute shortage for product
# with different order point
product_ids = [
p.id for p in sub_products
if (warehouse.id, p.id) not in product2ops_other]
# Search for shortage between min-max
shortages = cls.get_shortage(
warehouse.id, product_ids, min_date, max_date,
min_date_qties=min_date_qties,
order_points=product2ops)
for product in sub_products:
if product.id not in shortages:
continue
for date, quantity in shortages[product.id]:
order_point = product2ops.get(
(warehouse.id, product.id))
req = cls.compute_request(product, warehouse,
quantity, date, company, order_point)
req.set_planned_start_date()
requests.append(req)
cls.save(requests)
cls.set_moves(requests)
return requests
@classmethod
def compute_request(
cls, product, warehouse, quantity, date, company,
order_point=None, bom_pattern=None):
"""
Return the value of the production request.
"""
pool = Pool()
UoM = pool.get('product.uom')
Date = pool.get('ir.date')
with Transaction().set_context(company=company.id):
today = Date.today()
if date <= today:
date = today
else:
date -= datetime.timedelta(1)
pbom = product.get_bom(bom_pattern)
unit = product.default_uom
if pbom:
for output in pbom.bom.outputs:
if output.product == product:
# Use output unit to ensure the quantity requested is
# not floored to 0
unit = output.unit
quantity = UoM.compute_qty(
product.default_uom, quantity, unit, round=False)
break
quantity = unit.ceil(quantity)
if order_point:
origin = str(order_point)
else:
origin = 'stock.order_point,-1'
return cls(
planned_date=date,
company=company,
warehouse=warehouse,
location=warehouse.production_location,
product=product,
bom=pbom.bom if pbom else None,
unit=unit,
quantity=quantity,
state='request',
origin=origin,
)
@classmethod
def get_shortage(cls, location_id, product_ids, min_date, max_date,
min_date_qties, order_points):
"""
Return for each product a list of dates where the stock quantity is
less than the minimal quantity and the quantity to reach the maximal
quantity over the period.
The minimal and maximal quantities come from the order point or are
zero.
min_date_qty is the quantities for each product at the min date.
order_points is a dictionary that links products to order points.
"""
pool = Pool()
Product = pool.get('product.product')
shortages = defaultdict(list)
min_quantities = defaultdict(float)
target_quantities = defaultdict(float)
for product_id in product_ids:
order_point = order_points.get((location_id, product_id))
if order_point:
min_quantities[product_id] = order_point.min_quantity
target_quantities[product_id] = order_point.target_quantity
with Transaction().set_context(
forecast=True,
stock_date_start=min_date,
stock_date_end=max_date):
pbl = Product.products_by_location(
[location_id],
with_childs=True,
grouping=('date', 'product'),
grouping_filter=(None, product_ids))
pbl_dates = defaultdict(dict)
for key, qty in pbl.items():
date, product_id = key[1:]
pbl_dates[date][product_id] = qty
current_date = min_date
current_qties = min_date_qties.copy()
products_to_check = product_ids.copy()
while (current_date < max_date) or (current_date == min_date):
for product_id in products_to_check:
current_qty = current_qties[product_id]
min_quantity = min_quantities[product_id]
if min_quantity is not None and current_qty < min_quantity:
target_quantity = target_quantities[product_id]
quantity = target_quantity - current_qty
shortages[product_id].append((current_date, quantity))
current_qties[product_id] += quantity
if current_date == datetime.date.max:
break
current_date += datetime.timedelta(1)
pbl = pbl_dates[current_date]
products_to_check.clear()
for product_id, qty in pbl.items():
current_qties[product_id] += qty
products_to_check.append(product_id)
return shortages

View File

@@ -0,0 +1,34 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tryton>
<data>
<record model="ir.ui.view" id="production_configuration_view_form">
<field name="model">production.configuration</field>
<field name="inherit"
ref="production.production_configuration_view_form"/>
<field name="name">production_configuration_form</field>
</record>
<record model="ir.action.act_window" id="act_production_request">
<field name="name">Request Productions</field>
<field name="res_model">production</field>
<field name="search_value"
eval="[('state', '=', 'request')]" pyson="1"/>
</record>
<record model="ir.action.act_window.view"
id="act_production_request_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="production.production_view_list"/>
<field name="act_window" ref="act_production_request"/>
</record>
<record model="ir.action.act_window.view"
id="act_production_request_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="production.production_view_form"/>
<field name="act_window" ref="act_production_request"/>
</record>
</data>
</tryton>

View File

@@ -0,0 +1,100 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
import datetime
from trytond.i18n import gettext
from trytond.modules.stock_supply.exceptions import SupplyWarning
from trytond.pool import Pool, PoolMeta
from trytond.pyson import Eval, If
from trytond.transaction import check_access
from trytond.wizard import StateAction
class OrderPoint(metaclass=PoolMeta):
__name__ = 'stock.order_point'
@classmethod
def __setup__(cls):
super().__setup__()
cls.product.domain = [
cls.product.domain,
If(Eval('type') == 'production',
('producible', '=', True),
()),
]
option = ('production', 'Production')
if option not in cls.type.selection:
cls.type.selection.append(option)
@property
def warehouse_location(self):
location = super().warehouse_location
if self.type == 'production':
location = self.location
return location
class LocationLeadTime(metaclass=PoolMeta):
__name__ = 'stock.location.lead_time'
@classmethod
def _get_extra_lead_times(cls):
pool = Pool()
Configuration = pool.get('production.configuration')
config = Configuration(1)
supply_period = config.get_multivalue('supply_period')
extra = super()._get_extra_lead_times()
extra.append(supply_period or datetime.timedelta(0))
return extra
class StockSupply(metaclass=PoolMeta):
__name__ = 'stock.supply'
production = StateAction('stock_supply_production.act_production_request')
@classmethod
def types(cls):
return super().types() + ['production']
def transition_create_(self):
pool = Pool()
Date = pool.get('ir.date')
Move = pool.get('stock.move')
Warning = pool.get('res.user.warning')
today = Date.today()
with check_access():
moves = Move.search([
('from_location.type', '=', 'production'),
('to_location.type', '=', 'storage'),
('state', '=', 'draft'),
('planned_date', '<', today),
('production', 'not where', [
('state', '=', 'request'),
('origin', 'like', 'stock.order_point,%'),
]),
], order=[])
if moves:
key = '%s@%s' % (self.__name__, today)
if Warning.check(key):
raise SupplyWarning(
key,
gettext('stock_supply_production.msg_late_productions'))
return super().transition_create_()
@property
def _production_parameters(self):
return {
'warehouses': self.start.warehouses,
}
def generate_production(self, clean):
pool = Pool()
Production = pool.get('production')
return Production.generate_requests(
clean=clean, **self._production_parameters)
def transition_production(self):
return self.next_action('production')

View File

@@ -0,0 +1,15 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tryton>
<data>
<record model="ir.action.act_window.domain"
id="act_order_point_form_domain_production">
<field name="name">Production</field>
<field name="sequence" eval="30"/>
<field name="domain"
eval="[('type', '=', 'production')]" pyson="1"/>
<field name="act_window" ref="stock_supply.act_order_point_form"/>
</record>
</data>
</tryton>

View File

@@ -0,0 +1,2 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.

View File

@@ -0,0 +1,149 @@
===========================
Production Request Scenario
===========================
Imports::
>>> import datetime as dt
>>> from decimal import Decimal
>>> from proteus import Model, Wizard
>>> from trytond.modules.company.tests.tools import create_company
>>> from trytond.modules.stock.exceptions import MoveFutureWarning
>>> from trytond.tests.tools import activate_modules, assertEqual
>>> today = dt.date.today()
Activate modules::
>>> config = activate_modules('stock_supply_production', create_company)
>>> Warning = Model.get('res.user.warning')
Create product::
>>> ProductUom = Model.get('product.uom')
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
>>> ProductTemplate = Model.get('product.template')
>>> template = ProductTemplate()
>>> template.name = 'product'
>>> template.default_uom = unit
>>> template.type = 'goods'
>>> template.producible = True
>>> template.list_price = Decimal(30)
>>> template.save()
>>> product, = template.products
Define a supply period for production::
>>> ProductionConfiguration = Model.get('production.configuration')
>>> production_configuration = ProductionConfiguration(1)
>>> production_configuration.supply_period = dt.timedelta(days=30)
>>> production_configuration.save()
Get stock locations::
>>> Location = Model.get('stock.location')
>>> warehouse_loc, = Location.find([('code', '=', 'WH')])
>>> storage_loc, = Location.find([('code', '=', 'STO')])
>>> lost_loc, = Location.find([('type', '=', 'lost_found')])
Create needs for product::
>>> Move = Model.get('stock.move')
>>> move = Move()
>>> move.product = product
>>> move.quantity = 1
>>> move.from_location = storage_loc
>>> move.to_location = lost_loc
>>> move.click('do')
>>> move.state
'done'
>>> move, = move.duplicate(
... default={'effective_date': today + dt.timedelta(days=10)})
>>> try:
... move.click('do')
... except MoveFutureWarning as warning:
... Warning(user=config.user, name=warning.name).save()
>>> move.click('do')
There is no production request::
>>> Production = Model.get('production')
>>> Production.find([])
[]
Create production request::
>>> create_pr = Wizard('stock.supply')
>>> create_pr.execute('create_')
There is now a production request::
>>> productions = Production.find([])
>>> len(productions)
2
>>> {p.state for p in productions}
{'request'}
>>> for production in productions:
... assertEqual(production.product, product)
>>> sum(p.quantity for p in productions)
2.0
>>> assertEqual(sorted(p.planned_date for p in productions),
... [today, today + dt.timedelta(days=9)])
Create an order point negative minimal quantity::
>>> OrderPoint = Model.get('stock.order_point')
>>> order_point = OrderPoint()
>>> order_point.type = 'production'
>>> order_point.product = product
>>> order_point.location = warehouse_loc
>>> order_point.min_quantity = -2
>>> order_point.target_quantity = 10
>>> order_point.save()
Create production request::
>>> create_pr = Wizard('stock.supply')
>>> create_pr.execute('create_')
There is no more production request::
>>> Production = Model.get('production')
>>> Production.find([])
[]
Set a minimal quantity on order point::
>>> order_point.min_quantity = 5
>>> order_point.save()
Create production request::
>>> create_pr = Wizard('stock.supply')
>>> create_pr.execute('create_')
There is now a production request::
>>> production, = Production.find([])
>>> production.state
'request'
>>> assertEqual(production.product, product)
>>> production.quantity
11.0
Using zero as minimal quantity also creates a production request::
>>> order_point.min_quantity = 0
>>> order_point.save()
>>> create_pr = Wizard('stock.supply')
>>> create_pr.execute('create_')
>>> production, = Production.find([])
>>> production.state
'request'
>>> assertEqual(production.product, product)
>>> production.quantity
11.0

View File

@@ -0,0 +1,76 @@
====================================
Production Request with BoM Scenario
====================================
Imports::
>>> from proteus import Model, Wizard
>>> from trytond.modules.company.tests.tools import create_company
>>> from trytond.tests.tools import activate_modules, assertEqual
Activate modules::
>>> config = activate_modules('stock_supply_production', create_company)
>>> BoM = Model.get('production.bom')
>>> Location = Model.get('stock.location')
>>> Move = Model.get('stock.move')
>>> ProductTemplate = Model.get('product.template')
>>> ProductUom = Model.get('product.uom')
>>> Production = Model.get('production')
Create product with a BoM::
>>> unit, = ProductUom.find([('name', '=', 'Unit')])
>>> box = ProductUom(name="Box", symbol="b", category=unit.category)
>>> box.factor = 10
>>> box.rounding = 1
>>> box.digits = 0
>>> box.save()
>>> template = ProductTemplate()
>>> template.name = "product"
>>> template.default_uom = unit
>>> template.type = 'goods'
>>> template.producible = True
>>> template.save()
>>> product, = template.products
>>> bom = BoM(name="Product")
>>> output = bom.outputs.new()
>>> output.product = product
>>> output.quantity = 1
>>> output.unit = box
>>> bom.save()
>>> _ = product.boms.new(bom=bom)
>>> product.save()
Get stock locations::
>>> warehouse_loc, = Location.find([('code', '=', 'WH')])
>>> storage_loc, = Location.find([('code', '=', 'STO')])
>>> lost_loc, = Location.find([('type', '=', 'lost_found')])
Create needs for product::
>>> move = Move()
>>> move.product = product
>>> move.quantity = 2
>>> move.from_location = storage_loc
>>> move.to_location = lost_loc
>>> move.click('do')
>>> move.state
'done'
Create production request::
>>> create_pr = Wizard('stock.supply')
>>> create_pr.execute('create_')
>>> production, = Production.find([])
>>> assertEqual(production.product, product)
>>> production.quantity
1.0
>>> assertEqual(production.unit, box)

View File

@@ -0,0 +1,12 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.tests.test_tryton import ModuleTestCase
class StockSupplyProductionTestCase(ModuleTestCase):
'Test Stock Supply Production module'
module = 'stock_supply_production'
del ModuleTestCase

View File

@@ -0,0 +1,8 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.tests.test_tryton import load_doc_tests
def load_tests(*args, **kwargs):
return load_doc_tests(__name__, __file__, *args, **kwargs)

View File

@@ -0,0 +1,23 @@
[tryton]
version=7.8.0
depends:
ir
product
production
stock
stock_supply
xml:
production.xml
stock.xml
message.xml
[register]
model:
product.Product
stock.OrderPoint
stock.LocationLeadTime
production.Configuration
production.ConfigurationSupplyPeriod
production.Production
wizard:
stock.StockSupply

View File

@@ -0,0 +1,9 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<data>
<xpath expr="/form/field[@name='production_sequence']" position="after">
<label name="supply_period"/>
<field name="supply_period"/>
</xpath>
</data>