semen_extration_event.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. # -*- coding: utf-8 -*-
  2. # @authors: Alexander Ezquevo <alexander@acysos.com>
  3. # Copyright (C) 2015 Acysos S.L.
  4. # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
  5. from openerp import models, fields, api, _
  6. from openerp.exceptions import Warning
  7. import math
  8. class SemenExtractionEvent(models.Model):
  9. _name = 'farm.semen_extraction.event'
  10. _inherit = {'farm.event': 'AbstractEvent_id'}
  11. _auto = True
  12. semen_product = fields.Many2one(comodel_name='product.product',
  13. string="Semen's Product")
  14. untreated_semen_qty = fields.Float(string='Semen Extracted Qty',
  15. required=True, digits=(16, 3))
  16. formula_result = fields.Float(string='Formula Result', required=True)
  17. solvent_calculated_qty = fields.Float(string='Calc. semen solvent Qty',
  18. compute='get_solvent_qty')
  19. semen_calculated_qty = fields.Float(string='Calc. Semen Produced Qty',
  20. compute='get_semen_calculated_qty')
  21. semen_qty = fields.Float(string='Semen Producec Quantity', digits=(16, 3))
  22. semen_lot = fields.Many2one(comodel_name='stock.production.lot',
  23. string='Semen lot')
  24. semen_move = fields.Many2one(comodel_name='stock.move', string='Move')
  25. dose_location = fields.Many2one(comodel_name='stock.location',
  26. string='Doses Location',
  27. domain=[('usage', '=', 'internal')],
  28. required=True)
  29. dose_bom = fields.Many2one(comodel_name='mrp.bom',
  30. string='Dose Container',
  31. )
  32. dose_calculated_units = fields.Float(
  33. string='Calculated Doses',
  34. help='Calculates the number of doses based on Container (BoM) and '
  35. 'Semen Produced Qty. The quantity is expressed in the UoM of the '
  36. 'Container.\n'
  37. 'You have to save the event to see this calculated value.',
  38. compute='on_change_with_dose_calculated_units')
  39. doses = fields.One2many(comodel_name='farm.semen_extraction.dose',
  40. inverse_name='event', string='Doses')
  41. doses_semen_qty = fields.Float(string='Dose Semen Qty',
  42. compute='on_change_with_doses_semen_qty')
  43. semen_remaining_qty = fields.Float(
  44. string='Remaining Semen',
  45. compute='on_change_with_semen_remaining_qty')
  46. @api.onchange('specie')
  47. def onchange_specie(self):
  48. return {'domain': {
  49. 'semen_product': [('id', '=', self.specie.semen_product.id)]}}
  50. @api.one
  51. def get_solvent_qty(self):
  52. self.solvent_calculated_qty = \
  53. self.semen_calculated_qty - self.untreated_semen_qty
  54. @api.one
  55. def get_semen_calculated_qty(self):
  56. self.semen_calculated_qty = \
  57. self.untreated_semen_qty * self.formula_result
  58. @api.one
  59. def on_change_with_dose_calculated_units(self):
  60. if not self.dose_bom or not self.semen_qty:
  61. self.dose_calculated_units = 0.0
  62. else:
  63. consumed_semen_qty = 0.0
  64. for line in self.dose_bom.bom_line_ids:
  65. if line.product_id == self.specie.semen_product:
  66. consumed_semen_qty = line.product_qty
  67. if consumed_semen_qty == 0:
  68. self.dose_calculated_units = 0.0
  69. else:
  70. self.dose_calculated_units = \
  71. float(self.semen_qty)/consumed_semen_qty
  72. @api.one
  73. def on_change_with_semen_remaining_qty(self):
  74. semen_remaining_qty = self.semen_qty or 0
  75. if self.semen_qty is None or not self.doses:
  76. self.semen_remaining_qty = semen_remaining_qty
  77. else:
  78. for dose in self.doses:
  79. semen_remaining_qty -= dose.semen_qty or 0.0
  80. self.semen_remaining_qty = semen_remaining_qty
  81. @api.one
  82. def on_change_with_doses_semen_qty(self):
  83. if self.semen_qty is None or not self.doses:
  84. self.doses_semen_qty = 0.0
  85. else:
  86. doses_qty = 0.0
  87. for dose in self.doses:
  88. doses_qty += dose.semen_qty or 0.0
  89. self.doses_semen_qty = doses_qty
  90. def is_valid(self):
  91. for extraction_event in self:
  92. extraction_event.check_doses_semen_quantity()
  93. extraction_event.check_deliveries_dose_quantity()
  94. def check_doses_semen_quantity(self):
  95. if self.semen_remaining_qty < 0.0:
  96. raise Warning(
  97. _('More semen in doses than produced'))
  98. @api.one
  99. def calculate_doses(self):
  100. Dose_obj = self.env['farm.semen_extraction.dose']
  101. for extraction_event in self:
  102. if extraction_event.doses:
  103. raise Warning(
  104. _('dose already defined'))
  105. if not extraction_event.dose_bom:
  106. continue
  107. n_doses = math.floor(extraction_event.dose_calculated_units)
  108. Dose_obj.create({
  109. 'event': extraction_event.id,
  110. 'sequence': 1,
  111. 'bom': extraction_event.dose_bom.id,
  112. 'quantity': n_doses})
  113. @api.one
  114. def confirm(self):
  115. self.check_doses_semen_quantity()
  116. for extraction_event in self:
  117. if not extraction_event.doses:
  118. raise Warning(
  119. _('no doses'))
  120. self.get_semen_move()
  121. for dose in extraction_event.doses:
  122. dose.get_production()
  123. dose.state = 'validated'
  124. super(SemenExtractionEvent, extraction_event).confirm()
  125. @api.one
  126. def get_semen_move(self):
  127. move_obj = self.env['stock.move']
  128. lot_obj = self.env['stock.production.lot']
  129. new_lot = lot_obj.create({
  130. 'product_id': self.specie.semen_product.id})
  131. production_location = self.env['stock.location'].search(
  132. [('usage', '=', 'production')])
  133. new_move = move_obj.create({
  134. 'name': 'extrac' + new_lot.name,
  135. 'product_id': self.specie.semen_product.id,
  136. 'product_uom_qty': self.semen_qty,
  137. 'location_id': production_location.id,
  138. 'location_dest_id': self.dose_location.id,
  139. 'date': self.timestamp,
  140. 'company_id': self.farm.company_id.id,
  141. 'origin': 'extraction' + self.lot.name,
  142. 'product_uom':
  143. self.specie.semen_product.product_tmpl_id.uom_id.id,
  144. })
  145. new_move.action_done()
  146. for q in new_move.quant_ids:
  147. q.lot_id = new_lot.id
  148. self.semen_move = new_move
  149. self.semen_lot = new_lot
  150. class SemenExtractionDose(models.Model):
  151. _name = 'farm.semen_extraction.dose'
  152. _order = 'sequence ASC'
  153. event = fields.Many2one(comodel_name='farm.semen_extraction.event',
  154. string='Event')
  155. specie = fields.Many2one(comodel_name='farm.specie', string='Specie',
  156. compute='get_specie')
  157. state = fields.Selection(string='state',
  158. selection=[
  159. ('draft', 'Draft'),
  160. ('validated', 'Validated')],
  161. default='draft')
  162. sequence = fields.Integer(string='Line Num', required=True)
  163. bom = fields.Many2one(comodel_name='mrp.bom', string='Container',
  164. required=True,
  165. domain=[('semen_dose', '=', True), ])
  166. quantity = fields.Integer(string='Quantity', required=True)
  167. semen_qty = fields.Float(string='Semen Qty', compute='get_qty')
  168. dose_product = fields.Many2one(comodel_name='product.product',
  169. string="Dose Product")
  170. production = fields.Many2one(comodel_name='mrp.production',
  171. string='production')
  172. lot = fields.Many2one(comodel_name='stock.production.lot',
  173. string='Lot')
  174. @api.one
  175. def get_qty(self):
  176. if not self.event or not self.bom or not self.quantity:
  177. self.semen_qty = False
  178. else:
  179. semen_product = self.event.specie.semen_product
  180. semen_qty = 0.0
  181. for line in self.bom.bom_line_ids:
  182. if line.product_id == semen_product:
  183. semen_qty = line.product_qty*self.quantity
  184. break
  185. self.semen_qty = semen_qty
  186. @api.one
  187. def get_specie(self):
  188. self.specie = self.event.specie
  189. @api.one
  190. def get_production(self):
  191. production_location = self.env['stock.location'].search(
  192. [('usage', '=', 'production')])
  193. production_obj = self.env['mrp.production']
  194. products_obj = self.env['product.product']
  195. produce_line_obj = self.env['mrp.product.produce.line']
  196. wiz_product_produce_obj = self.env['mrp.product.produce']
  197. manu_product = products_obj.search(
  198. [('product_tmpl_id', '=', self.bom.product_tmpl_id.id)])
  199. new_production = production_obj.create({
  200. 'name': self.event,
  201. 'date_planned': self.event.timestamp,
  202. 'company_id': self.event.farm.company_id.id,
  203. 'product_id': manu_product.id,
  204. 'bom_id': self.bom.id,
  205. 'product_uom': self.bom.product_tmpl_id.uom_id.id,
  206. 'location_src_id': self.event.dose_location.id,
  207. 'location_dest_id': self.event.dose_location.id,
  208. 'product_qty': self.quantity,
  209. 'origin': self.event.job_order.name
  210. })
  211. new_production.action_confirm()
  212. new_production.action_ready()
  213. '''
  214. for line in new_production.move_lines:
  215. line.location_id = production_location
  216. '''
  217. lots_obj = self.env['stock.production.lot']
  218. new_lot = lots_obj.create({
  219. 'product_id': manu_product.id, })
  220. new_wiz_production = wiz_product_produce_obj.create({
  221. 'product_id': manu_product.id,
  222. 'product_qty': self.quantity,
  223. 'mode': 'consume_produce',
  224. 'lot_id': new_lot.id,
  225. })
  226. for line in new_production.move_lines:
  227. produce_line_obj.create({
  228. 'product_id': line.product_id.id,
  229. 'product_qty': line.product_uom_qty,
  230. 'lot_id': self.event.semen_lot.id,
  231. 'produce_id': new_wiz_production.id,
  232. })
  233. new_production.action_produce(self.quantity,
  234. 'consume_produce', new_wiz_production)
  235. new_production.action_production_end()
  236. self.production = new_production
  237. self.lot = new_lot