Class: ActivityProduction

Inherits:
Ekylibre::Record::Base show all
Includes:
Attachable, Customizable
Defined in:
app/models/activity_production.rb

Overview

Informations

License

Ekylibre - Simple agricultural ERP Copyright (C) 2008-2009 Brice Texier, Thibaud Merigon Copyright (C) 2010-2012 Brice Texier Copyright (C) 2012-2019 Brice Texier, David Joulin

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along with this program. If not, see www.gnu.org/licenses.

Table: activity_productions

activity_id         :integer          not null
campaign_id         :integer
created_at          :datetime         not null
creator_id          :integer
cultivable_zone_id  :integer
custom_fields       :jsonb
id                  :integer          not null, primary key
irrigated           :boolean          default(FALSE), not null
lock_version        :integer          default(0), not null
nitrate_fixing      :boolean          default(FALSE), not null
rank_number         :integer          not null
season_id           :integer
size_indicator_name :string           not null
size_unit_name      :string
size_value          :decimal(19, 4)   not null
started_on          :date
state               :string
stopped_on          :date
support_id          :integer          not null
support_nature      :string
support_shape       :geometry({:srid=>4326, :type=>"multi_polygon"})
tactic_id           :integer
updated_at          :datetime         not null
updater_id          :integer
usage               :string           not null

Instance Method Summary collapse

Methods included from Customizable

#custom_value, #set_custom_value, #validate_custom_fields

Methods inherited from Ekylibre::Record::Base

#already_updated?, #check_if_destroyable?, #check_if_updateable?, columns_definition, #customizable?, customizable?, #customized?, #destroyable?, #editable?, has_picture, #human_attribute_name, nomenclature_reflections, #old_record, #others, refers_to, #unsuppress, #updateable?

Methods included from Userstamp::Stampable

included

Methods included from Userstamp::Stamper

included

Instance Method Details

#active?Boolean

Returns:

  • (Boolean)

377
378
379
# File 'app/models/activity_production.rb', line 377

def active?
  activity.family.to_s != 'fallow_land'
end

#computed_support_nameObject


218
219
220
221
222
223
224
225
226
# File 'app/models/activity_production.rb', line 218

def computed_support_name
  list = []
  list << cultivable_zone.name if cultivable_zone
  list << campaign.name if campaign
  list << activity.name
  list << :rank.t(number: rank_number)
  list.reverse! if 'i18n.dir'.t == 'rtl'
  list.join(' ')
end

#computed_work_numberObject

compile unique work_number for support a : P_ for Parcel b : First letter of activity cultivation variety (v for vitis_vinifera, t for triticum) c : production rank number d : cultivable zone number (work number or cap number or id ) e : harvest year


234
235
236
237
238
239
240
241
# File 'app/models/activity_production.rb', line 234

def computed_work_number
  work_number = 'P'
  work_number << '_' << activity.cultivation_variety[0].upcase
  work_number << rank_number.to_s
  work_number << '_' << cultivable_zone.work_number || cultivable_zone.cap_number || cultivable_zone.id.to_s
  work_number << '_' + campaign.harvest_year.to_s if campaign
  work_number
end

#cost(role = :input) ⇒ Object


418
419
420
421
422
423
# File 'app/models/activity_production.rb', line 418

def cost(role = :input)
  costs = interventions.collect do |intervention|
    intervention.cost(role)
  end
  costs.compact.sum
end

#current_campaignObject

Used for find current campaign for given production


414
415
416
# File 'app/models/activity_production.rb', line 414

def current_campaign
  Campaign.at(Time.zone.now).first
end

#current_cultivationObject


673
674
675
676
677
678
# File 'app/models/activity_production.rb', line 673

def current_cultivation
  # get the first object with variety 'plant', availables
  if cultivation = support.contents.where(type: Plant).of_variety(variant.variety).availables.reorder(:born_at).first
    cultivation
  end
end

#current_size(options = {}) ⇒ Object

Compute quantity of a support as defined in production


685
686
687
688
689
690
# File 'app/models/activity_production.rb', line 685

def current_size(options = {})
  options[:at] ||= self.started_on ? self.started_on.to_time : Time.zone.now
  value = support.get(size_indicator_name, options)
  value = value.in(size_unit_name) if size_unit_name.present?
  value
end

#duplicate!(updates = {}) ⇒ Object


692
693
694
695
696
697
698
699
700
701
702
# File 'app/models/activity_production.rb', line 692

def duplicate!(updates = {})
  new_attributes = %i[
    activity campaign cultivable_zone irrigated nitrate_fixing
    size_indicator_name size_unit_name size_value started_on
    support_nature support_shape usage
  ].each_with_object({}) do |attr, h|
    h[attr] = send(attr)
    h
  end.merge(updates)
  self.class.create!(new_attributes)
end

#estimate_yield(campaign, options = {}) ⇒ Object

TODO: Which yield is computed? usage is not very good to determine yields

because many yields can be computed...

659
660
661
662
663
664
665
666
667
668
669
670
671
# File 'app/models/activity_production.rb', line 659

def estimate_yield(campaign, options = {})
  variety = options.delete(:variety)
  # compute variety for estimate yield
  if usage == 'grain' || usage == 'seed'
    variety ||= 'grain'
  elsif usage == 'fodder' || usage == 'fiber'
    variety ||= 'grass'
  end
  # get current campaign
  budget = activity.budget_of(campaign)
  return nil unless budget
  budget.estimate_yield(variety, options)
end

#fodder_yield(mass_unit_name = :ton, surface_unit_name = :hectare) ⇒ Object

Returns the yield of grain in mass per surface unit


633
634
635
636
637
638
# File 'app/models/activity_production.rb', line 633

def fodder_yield(mass_unit_name = :ton, surface_unit_name = :hectare)
  harvest_yield(:grass, procedure_category: :harvesting,
                        size_indicator_name: :net_mass,
                        size_unit_name: mass_unit_name,
                        surface_unit_name: surface_unit_name)
end

#fruit_yield(volume_unit_name = :ton, surface_unit_name = :hectare) ⇒ Object Also known as: vine_yield

Returns the yield of grape in volume per surface unit


649
650
651
652
653
654
# File 'app/models/activity_production.rb', line 649

def fruit_yield(volume_unit_name = :ton, surface_unit_name = :hectare)
  harvest_yield(:grape, procedure_category: :harvesting,
                        size_indicator_name: :net_volume,
                        size_unit_name: volume_unit_name,
                        surface_unit_name: surface_unit_name)
end

#get(*args) ⇒ Object


730
731
732
733
734
735
# File 'app/models/activity_production.rb', line 730

def get(*args)
  if support.blank?
    raise StandardError, "No support defined. Got: #{support.inspect}"
  end
  support.get(*args)
end

#grains_yield(mass_unit_name = :quintal, surface_unit_name = :hectare) ⇒ Object

Returns the yield of grain in mass per surface unit


625
626
627
628
629
630
# File 'app/models/activity_production.rb', line 625

def grains_yield(mass_unit_name = :quintal, surface_unit_name = :hectare)
  harvest_yield(:grain, procedure_category: :harvesting,
                        size_indicator_name: :net_mass,
                        size_unit_name: mass_unit_name,
                        surface_unit_name: surface_unit_name)
end

#harvest_yield(harvest_variety, options = {}) ⇒ Object

Generic method to get harvest yield


552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
# File 'app/models/activity_production.rb', line 552

def harvest_yield(harvest_variety, options = {})
  size_indicator_name = options[:size_indicator_name] || :net_mass
  ind = Nomen::Indicator.find(size_indicator_name)
  raise "Invalid indicator: #{size_indicator_name}" unless ind
  size_unit_name = options[:size_unit_name] || ind.unit
  unless Nomen::Unit.find(size_unit_name)
    raise "Invalid indicator unit: #{size_unit_name.inspect}"
  end
  surface_unit_name = options[:surface_unit_name] || :hectare
  procedure_category = options[:procedure_category] || :harvesting
  surface = net_surface_area
  unless surface && surface.to_d > 0
    Rails.logger.warn 'No surface area. Cannot compute harvest yield'
    return nil
  end
  harvest_yield_unit_name = "#{size_unit_name}_per_#{surface_unit_name}".to_sym
  # puts "harvest_yield_unit_name : #{harvest_yield_unit_name}".inspect.red
  unless Nomen::Unit.find(harvest_yield_unit_name)
    raise "Harvest yield unit doesn't exist: #{harvest_yield_unit_name.inspect}"
  end
  total_quantity = 0.0.in(size_unit_name)
  # puts "total_quantity : #{total_quantity}".inspect.red

  target_distribution_plants = Plant.where(activity_production: self)
  # get harvest_interventions firstly by distributions and secondly by inside_plants method
  # harvest_interventions = Intervention.real.of_category(procedure_category).with_targets(target_distribution_plants) if target_distribution_plants.any?
  # harvest_interventions ||= Intervention.real.of_category(procedure_category).with_targets(inside_plants)
  harvest_interventions ||= interventions.real.of_category(procedure_category)

  # puts "harvest_interventions count : #{harvest_interventions.count}".inspect.yellow

  coef_area = []
  global_coef_harvest_yield = []

  if harvest_interventions.any?
    harvest_interventions.includes(:targets).find_each do |harvest|
      harvest_working_area = []
      harvest.targets.each do |target|
        if zone = target.working_zone
          harvest_working_area << ::Charta.new_geometry(zone).area.in(:square_meter)
        end
      end
      # puts "harvest_working_area : #{harvest_working_area}".inspect.yellow
      harvest.outputs.each do |cast|
        actor = cast.product
        next unless actor && actor.variety
        variety = Nomen::Variety.find(actor.variety)
        if variety && variety <= harvest_variety
          quantity = cast.quantity_population.in(actor.variant.send(size_indicator_name).unit)
          total_quantity += quantity.convert(size_unit_name) if quantity
        end
      end
      # puts "total_quantity : #{total_quantity}".inspect.yellow
      h = harvest_working_area.compact.sum.to_d(surface_unit_name).to_f
      # puts "surface_unit_name : #{surface_unit_name}".inspect.green
      # puts "h : #{h}".inspect.green
      if h && h > 0.0
        global_coef_harvest_yield << (h * (total_quantity.to_f / h))
        coef_area << h
      end
      # puts "global_coef_harvest_yield : #{global_coef_harvest_yield}".inspect.green
      # puts "coef_area : #{coef_area}".inspect.green
    end
  end

  total_weighted_average_harvest_yield = global_coef_harvest_yield.compact.sum / coef_area.compact.sum if coef_area.compact.sum.to_d != 0.0
  # puts "total_weighted_average_harvest_yield : #{total_weighted_average_harvest_yield}".inspect.red
  m = Measure.new(total_weighted_average_harvest_yield.to_f, harvest_yield_unit_name)
  # puts "m : #{m}".inspect.red
  m.round(2)
end

#harvested_atObject

Returns the started_at attribute of the intervention of nature harvesting if exist and if it's a vegetal activity


545
546
547
548
549
# File 'app/models/activity_production.rb', line 545

def harvested_at
  intervention = interventions.real.of_category(:harvesting).first
  return intervention.started_at if intervention
  nil
end

#implanted_atObject

Returns the started_at attribute of the intervention of nature sowing if exist and if it's a vegetal activity


537
538
539
540
541
# File 'app/models/activity_production.rb', line 537

def implanted_at
  intervention = interventions.real.of_category(:planting).first
  return intervention.started_at if intervention
  nil
end

#initialize_animal_group_support!Object


309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
# File 'app/models/activity_production.rb', line 309

def initialize_animal_group_support!
  unless support
    self.support = AnimalGroup.new
    support.name = name
  end
  # FIXME: Need to find better category and population_counting...
  unless support.variant
    nature = ProductNature.find_or_create_by!(
      variety: :animal_group,
      derivative_of: :animal,
      name: AnimalGroup.model_name.human,
      category: ProductNatureCategory.import_from_nomenclature(:cattle_herd),
      population_counting: :unitary
    )
    variant = ProductNatureVariant.find_or_initialize_by(
      nature: nature,
      variety: :animal_group,
      derivative_of: :animal
    )
    variant.name ||= nature.name
    variant.unit_name ||= :unit.tl
    variant.save! if variant.new_record?
    support.variant = variant
  end
  if activity.cultivation_variety
    support.derivative_of ||= activity.cultivation_variety
  end
  support.save!
  if size_value.nil?
    errors.add(:size_value, :empty)
  else
    self.size = size_value.in(size_unit_name)
  end
end

#initialize_equipment_fleet_support!Object


344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
# File 'app/models/activity_production.rb', line 344

def initialize_equipment_fleet_support!
  self.support = EquipmentFleet.new unless support
  support.name = name
  # FIXME: Need to find better category and population_counting...
  unless support.variant
    nature = ProductNature.find_or_create_by!(
      variety: :equipment_fleet,
      derivative_of: :equipment,
      name: EquipmentFleet.model_name.human,
      category: ProductNatureCategory.import_from_nomenclature(:equipment_fleet),
      population_counting: :unitary
    )
    variant = ProductNatureVariant.find_or_initialize_by(
      nature: nature,
      variety: :equipment_fleet,
      derivative_of: :equipment
    )
    variant.name ||= nature.name
    variant.unit_name ||= :unit.tl
    variant.save! if variant.new_record?
    support.variant = variant
  end
  if activity.cultivation_variety
    support.derivative_of ||= activity.cultivation_variety
  end
  support.save!
  if size_value.nil?
    errors.add(:size_value, :empty)
  else
    self.size = size_value.in(size_unit_name)
  end
end

#initialize_land_parcel_support!Object


267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'app/models/activity_production.rb', line 267

def initialize_land_parcel_support!
  self.support_shape ||= cultivable_zone.shape if cultivable_zone
  unless support
    if self.support_shape
      land_parcels = LandParcel.shape_matching(self.support_shape)
                               .where.not(id: ActivityProduction.select(:support_id))
                               .order(:id)
      self.support = land_parcels.first if land_parcels.any?
    end
    self.support ||= LandParcel.new
  end
  support.name = name
  support.initial_shape = self.support_shape

  if self.activity && self.cultivable_zone
    support.work_number = computed_work_number
  end


  if support.initial_movement
    support.initial_movement.delta = support_shape_area.to_d(size_unit_name)
    support.initial_movement.started_at = started_on
    support.initial_movement.product = support
    support.initial_movement.save!
  end

  support.initial_population = support_shape_area.to_d(size_unit_name)
  support.initial_born_at = started_on
  support.initial_dead_at = stopped_on
  support.born_at = started_on
  support.dead_at = stopped_on
  support.variant ||= ProductNatureVariant.import_from_nomenclature(:land_parcel)
  support.save!
  reading = support.first_reading(:shape)
  if reading
    reading.value = self.support_shape
    reading.read_at = support.born_at
    reading.save!
  end
  self.size = support_shape_area.in(size_unit_name)
end

#input_cost(surface_unit_name = :hectare) ⇒ Object


504
505
506
507
508
509
510
# File 'app/models/activity_production.rb', line 504

def input_cost(surface_unit_name = :hectare)
  surface_area = net_surface_area
  if surface_area.to_s.to_f > 0.0
    return cost(:input) / surface_area.to_d(surface_unit_name).to_s.to_f
  end
  0.0
end

#inside_plantsObject

Returns all plants concerning by this activity production TODO: No plant here, a more generic method should be largely preferable


522
523
524
# File 'app/models/activity_production.rb', line 522

def inside_plants
  inside_products(Plant)
end

#inside_products(products = Product) ⇒ Object


526
527
528
529
530
531
532
533
# File 'app/models/activity_production.rb', line 526

def inside_products(products = Product)
  products = if campaign
               products.of_campaign(campaign)
             else
               products.where(born_at: started_on..(stopped_on || Time.zone.now.to_date))
             end
  products.shape_within(support_shape)
end

#interventions_by_weeksObject


385
386
387
388
389
390
391
392
393
# File 'app/models/activity_production.rb', line 385

def interventions_by_weeks
  interventions_by_week = {}
  interventions.each do |intervention|
    week_number = intervention.started_at.to_date.cweek
    interventions_by_week[week_number] ||= []
    interventions_by_week[week_number] << intervention
  end
  interventions_by_week
end

#interventions_of_nature(nature) ⇒ Object


243
244
245
246
# File 'app/models/activity_production.rb', line 243

def interventions_of_nature(nature)
  interventions
    .where(nature: nature)
end

#name(_options = {}) ⇒ Object

Returns unique i18nized name for given production


713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
# File 'app/models/activity_production.rb', line 713

def name(_options = {})
  interactor = NamingFormats::LandParcels::BuildActivityProductionNameInteractor
               .call(activity_production: self)

  return interactor.build_name if interactor.success?
  if interactor.fail?
    list = []
    list << activity.name
    list << campaign.harvest_year.to_s if activity.annual? && started_on
    # list << started_on.to_date.l(format: :month) if activity.annual? && started_on
    list << cultivable_zone.name if cultivable_zone && plant_farming?
    # list << :rank.t(number: rank_number)
    list = list.reverse! if 'i18n.dir'.t == 'rtl'
    list.join(' ')
  end
end

#nitrogen_balanceObject

TODO: for nitrogen balance but will be refactorize for any chemical components


466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
# File 'app/models/activity_production.rb', line 466

def nitrogen_balance
  # B = O - I
  balance = 0.0
  nitrogen_mass = []
  nitrogen_unity_per_hectare = nil
  if selected_manure_management_plan_zone
    # get the output O aka nitrogen_input from opened_at (in kg N / Ha )
    o = selected_manure_management_plan_zone.nitrogen_input || 0.0
    # get the nitrogen input I from opened_at to now (in kg N / Ha )
    opened_at = selected_manure_management_plan_zone.opened_at
    i = soil_enrichment_indicator_content_per_area(:nitrogen_concentration, opened_at, Time.zone.now)
    balance = o - i if i && o
  else
    balance = soil_enrichment_indicator_content_per_area(:nitrogen_concentration)
  end
  balance
end

#pfi_parcel_ratioObject


425
426
427
428
429
430
431
432
433
434
# File 'app/models/activity_production.rb', line 425

def pfi_parcel_ratio
  # compute pfi parcel ratio from pfi treatment ratios
  pfi_parcel_ratio = 0.0
  if interventions.any?
    i_ids = interventions.real.of_nature('spraying').pluck(:id)
    inputs = InterventionInput.where(intervention_id: i_ids, reference_name: 'plant_medicine')
    pfi_parcel_ratio = inputs.map(&:pfi_treatment_ratio).compact.sum
  end
  pfi_parcel_ratio
end

#phosphorus_balanceObject


488
489
490
# File 'app/models/activity_production.rb', line 488

def phosphorus_balance
  soil_enrichment_indicator_content_per_area(:phosphorus_concentration)
end

#potassium_balanceObject


484
485
486
# File 'app/models/activity_production.rb', line 484

def potassium_balance
  soil_enrichment_indicator_content_per_area(:potassium_concentration)
end

#provisional_nitrogen_inputObject


492
493
494
# File 'app/models/activity_production.rb', line 492

def provisional_nitrogen_input
  0
end

#season?Boolean

Returns:

  • (Boolean)

381
382
383
# File 'app/models/activity_production.rb', line 381

def season?
  !season_id.nil?
end

#soil_enrichment_indicator_content_per_area(indicator_name, from = nil, to = nil, area_unit_name = :hectare) ⇒ Object

Returns the spreaded quantity of one chemicals components (N, P, K) per area unit Get all intervention of category 'fertilizing' and sum all indicator unity spreaded

- indicator could be (:potassium_concentration, :nitrogen_concentration, :phosphorus_concentration)
- area_unit could be (:hectare, :square_meter)
- from and to used to select intervention

441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
# File 'app/models/activity_production.rb', line 441

def soil_enrichment_indicator_content_per_area(indicator_name, from = nil, to = nil, area_unit_name = :hectare)
  balance = []
  procedure_category = :fertilizing
  interventions = if from && to
                    self.interventions.real.of_category(procedure_category).between(from, to)
                  else
                    self.interventions.real.of_category(procedure_category)
                  end
  interventions.each do |intervention|
    intervention.inputs.each do |input|
      # m = net_mass of the input at intervention time
      # n = indicator (in %) of the input at intervention time
      m = (input.actor ? input.actor.net_mass(input).to_d(:kilogram) : 0.0)
      # TODO: for method phosphorus_concentration(input)
      n = (input.actor ? input.actor.send(indicator_name).to_d(:unity) : 0.0)
      balance << m * n
    end
  end
  # if net_surface_area, make the division
  area = net_surface_area.to_d(area_unit_name)
  indicator_unity_per_hectare = balance.compact.sum / area if area.nonzero?
  indicator_unity_per_hectare
end

#started_on_for(campaign) ⇒ Object


395
396
397
398
399
400
401
402
403
404
# File 'app/models/activity_production.rb', line 395

def started_on_for(campaign)
  return self.started_on if annual?
  on = begin
         Date.civil(campaign.harvest_year, self.started_on.month, self.started_on.day)
       rescue
         Date.civil(campaign.harvest_year, self.started_on.month, self.started_on.day - 1)
       end
  on -= 1.year if at_cycle_end?
  on
end

#stopped_on_for(campaign) ⇒ Object


406
407
408
409
410
411
# File 'app/models/activity_production.rb', line 406

def stopped_on_for(campaign)
  return stopped_on if annual?
  on = Date.civil(campaign.harvest_year, self.started_on.month, self.started_on.day) - 1
  on += 1.year if at_cycle_start?
  on
end

#time_cost(surface_unit_name = :hectare) ⇒ Object


512
513
514
515
516
517
518
# File 'app/models/activity_production.rb', line 512

def time_cost(surface_unit_name = :hectare)
  surface_area = net_surface_area
  if surface_area.to_s.to_f > 0.0
    return cost(:doer) / surface_area.to_d(surface_unit_name).to_s.to_f
  end
  0.0
end

#tool_cost(surface_unit_name = :hectare) ⇒ Object


496
497
498
499
500
501
502
# File 'app/models/activity_production.rb', line 496

def tool_cost(surface_unit_name = :hectare)
  surface_area = net_surface_area
  if surface_area.to_s.to_f > 0.0
    return cost(:tool) / surface_area.to_d(surface_unit_name).to_s.to_f
  end
  0.0
end

#unified_size_unitObject


680
681
682
# File 'app/models/activity_production.rb', line 680

def unified_size_unit
  size_unit_name.blank? ? :unity : size_unit_name
end

#update_namesObject


248
249
250
251
252
# File 'app/models/activity_production.rb', line 248

def update_names
  if support
    support.update_column(:name, name) if support.name != name
  end
end

#valid_period_for_support?Boolean

Returns:

  • (Boolean)

254
255
256
257
258
259
260
261
262
263
264
265
# File 'app/models/activity_production.rb', line 254

def valid_period_for_support?
  if self.started_on
    return false if self.started_on < Time.new(1, 1, 1).in_time_zone
  end
  if self.stopped_on
    return false if self.stopped_on >= Time.zone.now + 50.years
  end
  if self.started_on && self.stopped_on
    return false if self.started_on > self.stopped_on
  end
  true
end

#vegetable_yield(mass_unit_name = :ton, surface_unit_name = :hectare) ⇒ Object

Returns the yield of grain in mass per surface unit


641
642
643
644
645
646
# File 'app/models/activity_production.rb', line 641

def vegetable_yield(mass_unit_name = :ton, surface_unit_name = :hectare)
  harvest_yield(:grain, procedure_category: :harvesting,
                        size_indicator_name: :net_mass,
                        size_unit_name: mass_unit_name,
                        surface_unit_name: surface_unit_name)
end

#work_nameObject

LABEL METHODS ##


708
709
710
# File 'app/models/activity_production.rb', line 708

def work_name
  "#{support_work_number} - #{net_surface_area.convert(:hectare).round(2)}"
end