Add parcel weighing control | #044369
This commit is contained in:
parent
00bdff7485
commit
d528819286
|
@ -38,6 +38,7 @@ def register():
|
|||
weighing.Weighing,
|
||||
weighing.WeighingPlantation,
|
||||
weighing.WeighingDo,
|
||||
weighing.WeighingParcel,
|
||||
quality.Configuration,
|
||||
quality.ConfigurationCompany,
|
||||
quality.ProductQualitySample,
|
||||
|
|
|
@ -36,6 +36,9 @@ this repository contains the full copyright notices and license terms. -->
|
|||
<record model="ir.message" id="msg_move_amount_exceed">
|
||||
<field name="text">The move cannot be done because the amount of the move exceeds the set maximum amount.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_not_assigned_weight">
|
||||
<field name="text">The weighin weight is not distributed and its not being forced to analysis</field>
|
||||
</record>
|
||||
</data>
|
||||
|
||||
</tryton>
|
||||
|
|
16
plot.py
16
plot.py
|
@ -110,6 +110,16 @@ class Parcel(ModelSQL, ModelView):
|
|||
beneficiaries = fields.One2Many('agronomics.beneficiary', 'parcel',
|
||||
'Beneficiaries')
|
||||
all_do = fields.Function(fields.Char('All DO'), 'get_all_do')
|
||||
weighings = fields.One2Many('agronomics.weighing-agronomics.parcel',
|
||||
'parcel', 'Weighings')
|
||||
bought_quantity = fields.Function(
|
||||
fields.Float("Bought Quantity", digits=(16, 2)), 'get_bought_quantity')
|
||||
remaining_quantity = fields.Function(
|
||||
fields.Float("Remainig Quantity", digits=(16, 2)), 'get_remaining_quantity')
|
||||
|
||||
def get_rec_name(self, name):
|
||||
if self.plantation and self.crop:
|
||||
return self.plantation.code + ' - ' + self.crop.rec_name
|
||||
|
||||
@classmethod
|
||||
def validate(cls, records):
|
||||
|
@ -138,6 +148,12 @@ class Parcel(ModelSQL, ModelView):
|
|||
return round(float(min([x.max_production for x in max_production])
|
||||
)*self.surface, 2)
|
||||
|
||||
def get_bought_quantity(self, name):
|
||||
return sum([w.netweight for w in self.weighings if not w.table])
|
||||
|
||||
def get_remaining_quantity(self, name):
|
||||
return (self.max_production or 0) - (self.bought_quantity or 0)
|
||||
|
||||
|
||||
class ParcelDo(ModelSQL):
|
||||
"Parcel - Denomination Origin"
|
||||
|
|
|
@ -25,9 +25,14 @@
|
|||
<field name="irrigation"/>
|
||||
<label name="surface"/>
|
||||
<field name="surface"/>
|
||||
<label name="bought_quantity"/>
|
||||
<field name="bought_quantity"/>
|
||||
<label name="remaining_quantity"/>
|
||||
<field name="remaining_quantity"/>
|
||||
<newline/>
|
||||
<label name="tenure_regime"/>
|
||||
<field name="tenure_regime" colspan="3"/>
|
||||
<field name="denomination_origin" colspan="4"/>
|
||||
<field name="beneficiaries" colspan="4"/>
|
||||
<field name="weighings" colspan="4"/>
|
||||
</form>
|
||||
|
|
|
@ -10,5 +10,7 @@
|
|||
<field name="premium"/>
|
||||
<field name="producer"/>
|
||||
<field name="max_production"/>
|
||||
<field name="bought_quantity"/>
|
||||
<field name="remaining_quantity"/>
|
||||
<field name="denomination_origin" tree_invisible="1"/>
|
||||
</tree>
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
<page name="plantations">
|
||||
<field name="plantations" colspan="4"/>
|
||||
<field name="denomination_origin" colspan="4"/>
|
||||
<field name="parcels" colspan="4"/>
|
||||
</page>
|
||||
<page name="beneficiaries">
|
||||
<field name="beneficiaries" colspan="4"/>
|
||||
|
@ -45,7 +46,8 @@
|
|||
<button name="cancel" icon="tryton-cancel"/>
|
||||
<button name="draft"/>
|
||||
<button name="process" icon="tryton-forward"/>
|
||||
<button name="analysis" icon="tryton-forward"/>
|
||||
<button name="distribute" icon="tryton-forward"/>
|
||||
<button name="force_analysis" icon="tryton-forward"/>
|
||||
<button name="done" icon="tryton-forward"/>
|
||||
</group>
|
||||
</form>
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<form>
|
||||
<label name="weighing"/>
|
||||
<field name="weighing"/>
|
||||
<newline/>
|
||||
<label name="parcel"/>
|
||||
<field name="parcel"/>
|
||||
<newline/>
|
||||
<label name="netweight"/>
|
||||
<field name="netweight"/>
|
||||
</form>
|
|
@ -0,0 +1,6 @@
|
|||
<tree>
|
||||
<field name="weighing"/>
|
||||
<field name="parcel"/>
|
||||
<field name="netweight"/>
|
||||
<field name="table"/>
|
||||
</tree>
|
|
@ -0,0 +1,4 @@
|
|||
<tree sequence="sequence" editable="1">
|
||||
<field name="plantation"/>
|
||||
<field name="party"/>
|
||||
</tree>
|
129
weighing.py
129
weighing.py
|
@ -1,11 +1,13 @@
|
|||
# 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.model import fields, ModelSQL, ModelView, Workflow
|
||||
from trytond.model import fields, ModelSQL, ModelView, Workflow, sequence_ordered
|
||||
from trytond.pyson import Id, Eval, If
|
||||
from trytond.pool import Pool
|
||||
from trytond.i18n import gettext
|
||||
from trytond.exceptions import UserError
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.wizard import (Wizard, StateView, StateTransition, StateAction,
|
||||
Button)
|
||||
from datetime import datetime
|
||||
|
||||
class WeighingCenter(ModelSQL, ModelView):
|
||||
|
@ -19,8 +21,8 @@ class WeighingCenter(ModelSQL, ModelView):
|
|||
])
|
||||
|
||||
|
||||
READONLY = ['processing', 'in_analysis', 'done', 'cancelled']
|
||||
READONLY2 = ['draft', 'in_analysis', 'done', 'cancelled']
|
||||
READONLY = ['processing', 'distributed', 'in_analysis', 'done', 'cancelled']
|
||||
READONLY2 = ['draft', 'distributed', 'in_analysis', 'done', 'cancelled']
|
||||
|
||||
class Weighing(Workflow, ModelSQL, ModelView):
|
||||
""" Weighing """
|
||||
|
@ -86,14 +88,15 @@ class Weighing(Workflow, ModelSQL, ModelView):
|
|||
'readonly': Eval('state').in_(READONLY2),
|
||||
'required': Eval('state') == 'in_analysis',
|
||||
})
|
||||
plantations = fields.Many2Many('agronomics.weighing-agronomics.plantation',
|
||||
'weighing', 'plantation', 'plantations', states={
|
||||
plantations = fields.One2Many('agronomics.weighing-agronomics.plantation',
|
||||
'weighing', 'plantations', states={
|
||||
'readonly': Eval('state').in_(READONLY),
|
||||
'required': Eval('state') == 'process',
|
||||
}, size=4)
|
||||
state = fields.Selection([
|
||||
('draft', "Draft"),
|
||||
('processing', "Processing"),
|
||||
('distributed', "Distributed"),
|
||||
('in_analysis', "In Analysis"),
|
||||
('done', "Done"),
|
||||
('cancelled', "Cancelled"),
|
||||
|
@ -107,6 +110,11 @@ class Weighing(Workflow, ModelSQL, ModelView):
|
|||
'get_quality_test', 'set_quality_test')
|
||||
product_created = fields.Many2One('product.product', 'Product Created',
|
||||
readonly=True)
|
||||
parcels = fields.One2Many('agronomics.weighing-agronomics.parcel',
|
||||
'weighing', 'Parcels', readonly=True)
|
||||
not_assigned_weight = fields.Function(
|
||||
fields.Float('Not Assigned Weight'), 'get_not_assigned_weight')
|
||||
forced_analysis = fields.Boolean('Forced Analysis')
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
|
@ -118,6 +126,9 @@ class Weighing(Workflow, ModelSQL, ModelView):
|
|||
cls._transitions |= set((
|
||||
('draft', 'processing'),
|
||||
('processing', 'draft'),
|
||||
('processing', 'distributed'),
|
||||
('distributed', 'in_analysis'),
|
||||
('distributed', 'draft'),
|
||||
('processing', 'in_analysis'),
|
||||
('draft', 'cancelled'),
|
||||
('processing', 'cancelled'),
|
||||
|
@ -133,7 +144,7 @@ class Weighing(Workflow, ModelSQL, ModelView):
|
|||
'depends': ['state'],
|
||||
},
|
||||
'draft': {
|
||||
'invisible': ~Eval('state').in_(['processing']),
|
||||
'invisible': ~Eval('state').in_(['processing', 'distributed']),
|
||||
'icon': If(Eval('state') == 'cancelled',
|
||||
'tryton-undo',
|
||||
'tryton-back'),
|
||||
|
@ -143,10 +154,14 @@ class Weighing(Workflow, ModelSQL, ModelView):
|
|||
'invisible': Eval('state') != 'draft',
|
||||
'depends': ['state'],
|
||||
},
|
||||
'analysis': {
|
||||
'distribute': {
|
||||
'invisible': Eval('state') != 'processing',
|
||||
'depends': ['state'],
|
||||
},
|
||||
'force_analysis': {
|
||||
'invisible': Eval('state') != 'distributed',
|
||||
'depends': ['state'],
|
||||
},
|
||||
})
|
||||
|
||||
@staticmethod
|
||||
|
@ -173,7 +188,6 @@ class Weighing(Workflow, ModelSQL, ModelView):
|
|||
if not value:
|
||||
return
|
||||
|
||||
|
||||
@fields.depends('weighing_date')
|
||||
def on_change_with_crop(self):
|
||||
Crop = Pool().get('agronomics.crop')
|
||||
|
@ -186,8 +200,8 @@ class Weighing(Workflow, ModelSQL, ModelView):
|
|||
def get_parcel(self):
|
||||
if not self.plantations:
|
||||
return
|
||||
plantation = self.plantations[0]
|
||||
if not plantation.parcels:
|
||||
plantation = self.plantations[0].plantation
|
||||
if not plantation or not plantation.parcels:
|
||||
return
|
||||
return plantation.parcels[0]
|
||||
|
||||
|
@ -202,7 +216,7 @@ class Weighing(Workflow, ModelSQL, ModelView):
|
|||
def on_change_with_denomination_origin(self):
|
||||
parcel = self.get_parcel()
|
||||
if not parcel:
|
||||
return
|
||||
return []
|
||||
|
||||
return [x.id for x in parcel.denomination_origin]
|
||||
|
||||
|
@ -262,7 +276,7 @@ class Weighing(Workflow, ModelSQL, ModelView):
|
|||
if record.beneficiaries and abs(100 - round(percent, 2)) > 0.0001:
|
||||
raise UserError(gettext('agronomics.msg_beneficiaris_percent',
|
||||
crop=record.crop.rec_name,
|
||||
plantation=record.plantations[0].rec_name))
|
||||
plantation=record.plantations[0].plantation.rec_name))
|
||||
|
||||
@classmethod
|
||||
@Workflow.transition('in_analysis')
|
||||
|
@ -275,6 +289,8 @@ class Weighing(Workflow, ModelSQL, ModelView):
|
|||
with_rec_name=False)
|
||||
product = Product(**default_product_values)
|
||||
for weighing in weighings:
|
||||
if weighing.not_assigned_weight and not weighing.forced_analysis:
|
||||
raise UserError(gettext('agronomics.msg_not_assigned_weight'))
|
||||
product.template = weighing.product
|
||||
product.denominations_of_origin = weighing.denomination_origin
|
||||
if weighing.ecological:
|
||||
|
@ -293,6 +309,75 @@ class Weighing(Workflow, ModelSQL, ModelView):
|
|||
tests.append(weighing.create_quality_test())
|
||||
Quality.save(tests)
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
@Workflow.transition('distributed')
|
||||
def distribute(cls, weighings):
|
||||
pool = Pool()
|
||||
WeighingParcel = pool.get('agronomics.weighing-agronomics.parcel')
|
||||
weighing_parcel_to_save = []
|
||||
to_analysis = []
|
||||
for weighing in weighings:
|
||||
if not weighing.table:
|
||||
if weighing.parcels:
|
||||
WeighingParcel.delete(weighing.parcels)
|
||||
allowed_parcels = []
|
||||
remaining_weight = weighing.netweight
|
||||
for wp in weighing.plantations:
|
||||
plantation = wp.plantation
|
||||
if plantation:
|
||||
for parcel in plantation.parcels:
|
||||
if parcel.crop == weighing.crop:
|
||||
allowed_parcels.append(parcel)
|
||||
break
|
||||
for parcel in allowed_parcels:
|
||||
if not remaining_weight:
|
||||
break
|
||||
weighing_parcel = WeighingParcel()
|
||||
weighing_parcel.parcel = parcel
|
||||
weighing_parcel.weighing = weighing
|
||||
if parcel.remaining_quantity - remaining_weight >= 0:
|
||||
weighing_parcel.netweight = remaining_weight
|
||||
remaining_weight = 0
|
||||
else:
|
||||
remaining_weight -= parcel.remaining_quantity
|
||||
weighing_parcel.netweight = parcel.remaining_quantity
|
||||
if weighing_parcel.netweight:
|
||||
weighing_parcel_to_save.append(weighing_parcel)
|
||||
if remaining_weight == 0:
|
||||
to_analysis.append(weighing)
|
||||
else:
|
||||
parcel = weighing.get_parcel()
|
||||
weighing_parcel = WeighingParcel()
|
||||
weighing_parcel.parcel = parcel
|
||||
weighing_parcel.weighing = weighing
|
||||
weighing_parcel.netweight = weighing.netweight
|
||||
weighing_parcel.table = True
|
||||
weighing_parcel_to_save.append(weighing_parcel)
|
||||
to_analysis.append(weighing)
|
||||
WeighingParcel.save(weighing_parcel_to_save)
|
||||
cls.save(weighings)
|
||||
cls.analysis(to_analysis)
|
||||
|
||||
def get_not_assigned_weight(self, name):
|
||||
return self.netweight - sum([p.netweight for p in self.parcels])
|
||||
|
||||
@classmethod
|
||||
@ModelView.button
|
||||
def force_analysis(cls, weighings):
|
||||
to_copy_values = {}
|
||||
for weighing in weighings:
|
||||
to_copy_values[weighing.id] = {'netweight': weighing.not_assigned_weight}
|
||||
cls.copy(weighings, default={
|
||||
'netweight': lambda d: (
|
||||
to_copy_values[d['id']]['netweight']),
|
||||
})
|
||||
for weighing in weighings:
|
||||
weighing.forced_analysis = True
|
||||
weighing.netweight -= weighing.not_assigned_weight
|
||||
cls.save(weighings)
|
||||
cls.analysis(weighings)
|
||||
|
||||
def create_quality_test(self):
|
||||
pool = Pool()
|
||||
QualityTest = pool.get('quality.test')
|
||||
|
@ -371,6 +456,8 @@ class Weighing(Workflow, ModelSQL, ModelView):
|
|||
default = default.copy()
|
||||
default.setdefault('beneficiaries', None)
|
||||
default.setdefault('product_created', None)
|
||||
default.setdefault('number', None)
|
||||
default.setdefault('parcels', None)
|
||||
return super().copy(weighings, default=default)
|
||||
|
||||
|
||||
|
@ -383,10 +470,26 @@ class WeighingDo(ModelSQL):
|
|||
'Denomination Origin')
|
||||
|
||||
|
||||
class WeighingPlantation(ModelSQL):
|
||||
class WeighingPlantation(sequence_ordered(), ModelSQL, ModelView):
|
||||
'Weighing - Plantations'
|
||||
__name__ = 'agronomics.weighing-agronomics.plantation'
|
||||
|
||||
weighing = fields.Many2One('agronomics.weighing', 'Weighing')
|
||||
plantation = fields.Many2One('agronomics.plantation',
|
||||
'Plantation')
|
||||
party = fields.Function(fields.Many2One('party.party', 'Party'), 'get_party')
|
||||
|
||||
def get_party(self, name):
|
||||
if self.plantation:
|
||||
return self.plantation.party.id
|
||||
|
||||
|
||||
class WeighingParcel(ModelSQL, ModelView):
|
||||
"Wheighing-Parcel"
|
||||
__name__ = 'agronomics.weighing-agronomics.parcel'
|
||||
|
||||
weighing = fields.Many2One('agronomics.weighing', 'Weighing',
|
||||
ondelete='CASCADE')
|
||||
parcel = fields.Many2One('agronomics.parcel', 'Parcel')
|
||||
netweight = fields.Float('Net Weight')
|
||||
table = fields.Boolean('Table')
|
||||
|
|
|
@ -168,11 +168,6 @@
|
|||
<field name="group" ref="group_agronomics"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="weighing_analysis_button">
|
||||
<field name="name">analysis</field>
|
||||
<field name="string">Analysis</field>
|
||||
<field name="model" search="[('model', '=', 'agronomics.weighing')]"/>
|
||||
</record>
|
||||
<record model="ir.model.button-res.group" id="weighing_analysis_button_group_agronomics">
|
||||
<field name="button" ref="weighing_analysis_button"/>
|
||||
<field name="group" ref="group_agronomics"/>
|
||||
|
@ -198,5 +193,42 @@
|
|||
<field name="group" ref="group_agronomics"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="weighing_distribute_button">
|
||||
<field name="name">distribute</field>
|
||||
<field name="string">Analysis</field>
|
||||
<field name="model" search="[('model', '=', 'agronomics.weighing')]"/>
|
||||
</record>
|
||||
<record model="ir.model.button-res.group" id="weighing_distribute_button_group_agronomics">
|
||||
<field name="button" ref="weighing_distribute_button"/>
|
||||
<field name="group" ref="group_agronomics"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.model.button" id="weighing_force_analysis_button">
|
||||
<field name="name">force_analysis</field>
|
||||
<field name="string">Force Analysis</field>
|
||||
<field name="model" search="[('model', '=', 'agronomics.weighing')]"/>
|
||||
</record>
|
||||
<record model="ir.model.button-res.group" id="weighing_force_analysis_button_group_agronomics">
|
||||
<field name="button" ref="weighing_force_analysis_button"/>
|
||||
<field name="group" ref="group_agronomics"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="weighing_parcel_view_form">
|
||||
<field name="model">agronomics.weighing-agronomics.parcel</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">weighing_parcel_form</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="weighing_parcel_view_tree">
|
||||
<field name="model">agronomics.weighing-agronomics.parcel</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">weighing_parcel_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="weighing_plantation_view_tree">
|
||||
<field name="model">agronomics.weighing-agronomics.plantation</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">weighing_plantation_list</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</tryton>
|
||||
|
|
Loading…
Reference in New Issue