Add parcel weighing control | #044369

This commit is contained in:
Jared Esparza 2022-02-21 14:10:47 +01:00
parent 00bdff7485
commit d528819286
11 changed files with 203 additions and 19 deletions

View File

@ -38,6 +38,7 @@ def register():
weighing.Weighing,
weighing.WeighingPlantation,
weighing.WeighingDo,
weighing.WeighingParcel,
quality.Configuration,
quality.ConfigurationCompany,
quality.ProductQualitySample,

View File

@ -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
View File

@ -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"

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -0,0 +1,6 @@
<tree>
<field name="weighing"/>
<field name="parcel"/>
<field name="netweight"/>
<field name="table"/>
</tree>

View File

@ -0,0 +1,4 @@
<tree sequence="sequence" editable="1">
<field name="plantation"/>
<field name="party"/>
</tree>

View File

@ -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')

View File

@ -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>