You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

333 lines
16 KiB

  1. # -*- coding: utf-8 -*-
  2. from datetime import datetime
  3. from openerp import api, fields, models, _
  4. from openerp.exceptions import ValidationError
  5. class operation_request(models.Model):
  6. _name = 'operation.request'
  7. def get_date_now(self):
  8. return datetime.strftime(datetime.now(), '%Y-%m-%d')
  9. @api.multi
  10. @api.depends('share_product_id', 'share_product_id.list_price', 'quantity')
  11. def _compute_subscription_amount(self):
  12. for operation_request in self:
  13. operation_request.subscription_amount = (operation_request.
  14. share_product_id.
  15. list_price *
  16. operation_request.
  17. quantity)
  18. request_date = fields.Date(string='Request date',
  19. default=lambda self: self.get_date_now())
  20. effective_date = fields.Date(string='Effective date')
  21. partner_id = fields.Many2one('res.partner',
  22. string='Cooperator',
  23. domain=[('member', '=', True)],
  24. required=True)
  25. partner_id_to = fields.Many2one('res.partner',
  26. string='Transfered to',
  27. domain=[('cooperator', '=', True)])
  28. operation_type = fields.Selection([('subscription', 'Subscription'),
  29. ('transfer', 'Transfer'),
  30. ('sell_back', 'Sell Back'),
  31. ('convert', 'Conversion')],
  32. string='Operation Type',
  33. required=True)
  34. share_product_id = fields.Many2one('product.product',
  35. string='Share type',
  36. domain=[('is_share', '=', True)],
  37. required=True)
  38. share_to_product_id = fields.Many2one('product.product',
  39. string='Convert to this share type',
  40. domain=[('is_share', '=', True)])
  41. share_short_name = fields.Char(related='share_product_id.short_name',
  42. string='Share type name')
  43. share_to_short_name = fields.Char(related='share_to_product_id.short_name',
  44. string='Share to type name')
  45. share_unit_price = fields.Float(related='share_product_id.list_price',
  46. string='Share price')
  47. share_to_unit_price = fields.Float(related='share_to_product_id.list_price',
  48. string='Share to price')
  49. subscription_amount = fields.Float(compute='_compute_subscription_amount',
  50. string='Operation amount')
  51. quantity = fields.Integer(string='Number of share',
  52. required=True)
  53. state = fields.Selection([('draft', 'Draft'),
  54. ('waiting', 'Waiting'),
  55. ('approved', 'Approved'),
  56. ('done', 'Done'),
  57. ('cancelled', 'Cancelled'),
  58. ('refused', 'Refused')],
  59. string='State',
  60. required=True,
  61. default='draft')
  62. user_id = fields.Many2one('res.users',
  63. string='Responsible',
  64. readonly=True,
  65. default=lambda self: self.env.user)
  66. subscription_request = fields.One2many('subscription.request',
  67. 'operation_request_id',
  68. string="Share Receiver Info",
  69. help="In case on a transfer of"
  70. " share. If the share receiver"
  71. " isn't a effective member then a"
  72. " subscription form should"
  73. " be filled.")
  74. receiver_not_member = fields.Boolean(string='Receiver is not a member')
  75. company_id = fields.Many2one('res.company',
  76. string='Company',
  77. required=True,
  78. change_default=True,
  79. readonly=True,
  80. default=lambda self: self.env['res.company']._company_default_get())
  81. invoice = fields.Many2one('account.invoice',
  82. string="Invoice")
  83. @api.multi
  84. @api.constrains("effective_date")
  85. def _constrain_effective_date(self):
  86. for obj in self:
  87. if obj.effective_date > fields.Datetime.now():
  88. raise ValidationError(
  89. _("The effective date can not be in the future.")
  90. )
  91. @api.multi
  92. def approve_operation(self):
  93. for rec in self:
  94. rec.write({'state': 'approved'})
  95. @api.multi
  96. def refuse_operation(self):
  97. for rec in self:
  98. rec.write({'state': 'refused'})
  99. @api.multi
  100. def submit_operation(self):
  101. for rec in self:
  102. rec.validate()
  103. rec.write({'state': 'waiting'})
  104. @api.multi
  105. def cancel_operation(self):
  106. for rec in self:
  107. rec.write({'state': 'cancelled'})
  108. @api.multi
  109. def reset_to_draft(self):
  110. for rec in self:
  111. rec.write({'state': 'draft'})
  112. def get_total_share_dic(self, partner):
  113. total_share_dic = {}
  114. prod_template_obj = self.env['product.product']
  115. share_products = prod_template_obj.search([('is_share', '=', True)])
  116. for share_product in share_products:
  117. total_share_dic[share_product.id] = 0
  118. for line in partner.share_ids:
  119. total_share_dic[line.share_product_id.id] += line.share_number
  120. return total_share_dic
  121. # This function doesn't handle the case of a cooperator can own
  122. # different kinds of share type
  123. def hand_share_over(self, partner, share_product_id, quantity):
  124. if not partner.member:
  125. raise ValidationError(_("This operation can't be executed if the"
  126. " cooperator is not an effective member"))
  127. share_ind = len(partner.share_ids)
  128. i = 1
  129. while quantity > 0:
  130. line = self.partner_id.share_ids[share_ind-i]
  131. if line.share_product_id.id == share_product_id.id:
  132. if quantity > line.share_number:
  133. quantity -= line.share_number
  134. line.unlink()
  135. else:
  136. share_left = line.share_number - quantity
  137. quantity = 0
  138. line.write({'share_number': share_left})
  139. i += 1
  140. # if the cooperator sold all his shares he's no more
  141. # an effective member
  142. remaning_share_dict = 0
  143. for share_quant in self.get_total_share_dic(partner).values():
  144. remaning_share_dict += share_quant
  145. if remaning_share_dict == 0:
  146. self.partner_id.write({'member': False, 'old_member': True})
  147. def has_share_type(self):
  148. for line in self.partner_id.share_ids:
  149. if line.share_product_id.id == self.share_product_id.id:
  150. return True
  151. return False
  152. def validate(self):
  153. if not self.has_share_type() and \
  154. self.operation_type in ['sell_back', 'transfer']:
  155. raise ValidationError(_("The cooperator doesn't own this share"
  156. " type. Please choose the appropriate"
  157. " share type."))
  158. if self.operation_type in ['sell_back', 'convert', 'transfer']:
  159. total_share_dic = self.get_total_share_dic(self.partner_id)
  160. if self.quantity > total_share_dic[self.share_product_id.id]:
  161. raise ValidationError(_("The cooperator can't hand over more"
  162. " shares that he/she owns."))
  163. if self.operation_type == 'convert':
  164. amount_to_convert = self.share_unit_price * self.quantity
  165. share_price = self.share_to_product_id.list_price
  166. remainder = amount_to_convert % share_price
  167. if remainder != 0:
  168. raise ValidationError(_("The conversion must give a whole"
  169. " number for quantity"))
  170. if self.company_id.unmix_share_type:
  171. if self.share_product_id.code == self.share_to_product_id.code:
  172. raise ValidationError(_("You can't convert the share to"
  173. " the same share type."))
  174. if self.subscription_amount != self.partner_id.total_value:
  175. raise ValidationError(_("You must convert all the shares"
  176. " to the selected type."))
  177. else:
  178. if self.subscription_amount != self.partner_id.total_value:
  179. raise ValidationError(_("Converting just part of the"
  180. " shares is not yet implemented"))
  181. elif self.operation_type == 'transfer':
  182. if not self.receiver_not_member and self.company_id.unmix_share_type \
  183. and (self.partner_id_to.cooperator_type
  184. and self.partner_id.cooperator_type != self.partner_id_to.cooperator_type):
  185. raise ValidationError(_("This share type could not be"
  186. " transfered to " +
  187. self.partner_id_to.name))
  188. if self.partner_id_to.is_company \
  189. and not self.share_product_id.by_company:
  190. raise ValidationError(_("This share can not be"
  191. " subscribed by a company"))
  192. if not self.partner_id_to.is_company \
  193. and not self.share_product_id.by_individual:
  194. raise ValidationError(_("This share can not be"
  195. " subscribed an individual"))
  196. if self.receiver_not_member and self.subscription_request \
  197. and not self.subscription_request.validated:
  198. raise ValidationError(_("The information of the receiver"
  199. " are not correct. Please correct"
  200. " the information before"
  201. " submitting"))
  202. @api.multi
  203. def execute_operation(self):
  204. self.ensure_one()
  205. if self.effective_date:
  206. effective_date = self.effective_date
  207. else:
  208. effective_date = self.get_date_now()
  209. self.effective_date = effective_date
  210. sub_request = self.env['subscription.request']
  211. for rec in self:
  212. rec.validate()
  213. if rec.state != 'approved':
  214. raise ValidationError(_("This operation must be approved"
  215. " before to be executed"))
  216. values = {
  217. 'partner_id': rec.partner_id.id, 'quantity': rec.quantity,
  218. 'share_product_id': rec.share_product_id.id,
  219. 'type': rec.operation_type,
  220. 'share_unit_price': rec.share_unit_price,
  221. 'date': effective_date,
  222. }
  223. if rec.operation_type == 'sell_back':
  224. self.hand_share_over(rec.partner_id, rec.share_product_id,
  225. rec.quantity)
  226. elif rec.operation_type == 'convert':
  227. amount_to_convert = rec.share_unit_price * rec.quantity
  228. convert_quant = int(amount_to_convert / rec.share_to_product_id.list_price)
  229. remainder = amount_to_convert % rec.share_to_product_id.list_price
  230. if convert_quant > 0 and remainder == 0:
  231. share_ids = rec.partner_id.share_ids
  232. line = share_ids[0]
  233. if len(share_ids) > 1:
  234. share_ids[1:len(share_ids)].unlink()
  235. line.write({
  236. 'share_number': convert_quant,
  237. 'share_product_id': rec.share_to_product_id.id,
  238. 'share_unit_price': rec.share_to_unit_price,
  239. 'share_short_name': rec.share_to_short_name
  240. })
  241. values['share_to_product_id'] = rec.share_to_product_id.id
  242. values['quantity_to'] = convert_quant
  243. else:
  244. raise ValidationError(_("Converting just part of the"
  245. " shares is not yet implemented"))
  246. elif rec.operation_type == 'transfer':
  247. sequence_id = self.env.ref('easy_my_coop.sequence_subscription', False)
  248. if rec.receiver_not_member:
  249. partner = rec.subscription_request.create_coop_partner()
  250. # get cooperator number
  251. sub_reg_num = int(sequence_id.next_by_id())
  252. partner_vals = sub_request.get_eater_vals(partner, rec.share_product_id)
  253. partner_vals['member'] = True
  254. partner_vals['cooperator_register_number'] = sub_reg_num
  255. partner.write(partner_vals)
  256. rec.partner_id_to = partner
  257. else:
  258. # means an old member or cooperator candidate
  259. if not rec.partner_id_to.member:
  260. if rec.partner_id_to.cooperator_register_number == 0:
  261. sub_reg_num = int(sequence_id.next_by_id())
  262. partner_vals['cooperator_register_number'] = sub_reg_num
  263. partner_vals = sub_request.get_eater_vals(
  264. rec.partner_id_to,
  265. rec.share_product_id)
  266. partner_vals['member'] = True
  267. partner_vals['old_member'] = False
  268. rec.partner_id_to.write(partner_vals)
  269. # remove the parts to the giver
  270. self.hand_share_over(rec.partner_id,
  271. rec.share_product_id,
  272. rec.quantity)
  273. # give the share to the receiver
  274. self.env['share.line'].create({
  275. 'share_number': rec.quantity,
  276. 'partner_id': rec.partner_id_to.id,
  277. 'share_product_id': rec.share_product_id.id,
  278. 'share_unit_price': rec.share_unit_price,
  279. 'effective_date': effective_date})
  280. values['partner_id_to'] = rec.partner_id_to.id
  281. else:
  282. raise ValidationError(_("This operation is not yet"
  283. " implemented."))
  284. sequence_operation = self.env.ref('easy_my_coop.sequence_register_operation', False)
  285. sub_reg_operation = sequence_operation.next_by_id()
  286. values['name'] = sub_reg_operation
  287. values['register_number_operation'] = int(sub_reg_operation)
  288. rec.write({'state': 'done'})
  289. # send mail to the receiver
  290. if rec.operation_type == 'transfer':
  291. certificat_email_template = self.env.ref('easy_my_coop.email_template_share_transfer', False)
  292. certificat_email_template.send_mail(rec.partner_id_to.id, False)
  293. self.env['subscription.register'].create(values)
  294. certificat_email_template = self.env.ref('easy_my_coop.email_template_share_update', False)
  295. certificat_email_template.send_mail(rec.partner_id.id, False)