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.

703 lines
32 KiB

6 years ago
6 years ago
6 years ago
6 years ago
5 years ago
  1. from datetime import datetime
  2. from odoo import api, fields, models, _
  3. from odoo.addons.base_iban.models.res_partner_bank import validate_iban
  4. from odoo.exceptions import UserError, ValidationError
  5. _REQUIRED = ['email',
  6. 'firstname',
  7. 'lastname',
  8. 'birthdate',
  9. 'address',
  10. 'share_product_id',
  11. 'ordered_parts',
  12. 'zip_code',
  13. 'city',
  14. 'iban',
  15. 'no_registre',
  16. 'gender']
  17. @api.model
  18. def _lang_get(self):
  19. languages = self.env['res.lang'].search([])
  20. return [(language.code, language.name) for language in languages]
  21. class SubscriptionRequest(models.Model):
  22. _name = 'subscription.request'
  23. _description = 'Subscription Request'
  24. def get_required_field(self):
  25. required_fields = _REQUIRED
  26. company = self.env['res.company']._company_default_get()
  27. if company.data_policy_approval_required:
  28. required_fields.append('data_policy_approved')
  29. if company.internal_rules_approval_required:
  30. required_fields.append('internal_rules_approved')
  31. return required_fields
  32. def get_mail_template_notif(self):
  33. return 'easy_my_coop.email_template_confirmation'
  34. def is_member(self, vals, cooperator):
  35. if cooperator.member:
  36. vals['type'] = 'increase'
  37. vals['already_cooperator'] = True
  38. return vals
  39. @api.model
  40. def create(self, vals):
  41. partner_obj = self.env['res.partner']
  42. mail_template = self.get_mail_template_notif()
  43. if not vals.get('partner_id'):
  44. cooperator = False
  45. if vals.get('email'):
  46. cooperator = partner_obj.get_cooperator_from_email(
  47. vals.get('email'))
  48. if cooperator:
  49. # TODO remove the following line of code once it has
  50. # been found a way to avoid double encoding
  51. cooperator = cooperator[0]
  52. vals['type'] = 'subscription'
  53. vals = self.is_member(vals, cooperator)
  54. vals['partner_id'] = cooperator.id
  55. if not cooperator.cooperator:
  56. cooperator.write({'cooperator': True})
  57. else:
  58. cooperator_id = vals.get('partner_id')
  59. cooperator = partner_obj.browse(cooperator_id)
  60. vals = self.is_member(vals, cooperator)
  61. subscr_request = super(SubscriptionRequest, self).create(vals)
  62. confirmation_mail_template = self.env.ref(mail_template, False)
  63. confirmation_mail_template.send_mail(subscr_request.id)
  64. return subscr_request
  65. @api.model
  66. def create_comp_sub_req(self, vals):
  67. vals["name"] = vals['company_name']
  68. if not vals.get('partner_id'):
  69. cooperator = self.env['res.partner'].get_cooperator_from_crn(vals.get('company_register_number'))
  70. if cooperator:
  71. vals['partner_id'] = cooperator.id
  72. vals['type'] = 'increase'
  73. vals['already_cooperator'] = True
  74. subscr_request = super(SubscriptionRequest, self).create(vals)
  75. confirmation_mail_template = self.env.ref('easy_my_coop.email_template_confirmation_company', False)
  76. confirmation_mail_template.send_mail(subscr_request.id, True)
  77. return subscr_request
  78. def check_empty_string(self, value):
  79. if value is None or value is False or value == '':
  80. return False
  81. return True
  82. def check_iban(self, iban):
  83. validated = True
  84. try:
  85. validate_iban(iban)
  86. except ValidationError:
  87. validated = False
  88. return validated
  89. @api.multi
  90. @api.depends('iban', 'skip_control_ng', 'is_company')
  91. def _validated_lines(self):
  92. for sub_request in self:
  93. validated = self.check_iban(sub_request.iban)
  94. sub_request.validated = validated
  95. @api.multi
  96. @api.depends('share_product_id',
  97. 'share_product_id.list_price',
  98. 'ordered_parts')
  99. def _compute_subscription_amount(self):
  100. for sub_request in self:
  101. sub_request.subscription_amount = (sub_request.share_product_id.
  102. list_price *
  103. sub_request.ordered_parts)
  104. already_cooperator = fields.Boolean(string="I'm already cooperator",
  105. readonly=True,
  106. states={'draft': [('readonly', False)]}
  107. )
  108. name = fields.Char(string='Name',
  109. required=True,
  110. readonly=True,
  111. states={'draft': [('readonly', False)]})
  112. firstname = fields.Char(string='Firstname',
  113. readonly=True,
  114. states={'draft': [('readonly', False)]})
  115. lastname = fields.Char(string='Lastname',
  116. readonly=True,
  117. states={'draft': [('readonly', False)]})
  118. birthdate = fields.Date(string="Birthdate",
  119. readonly=True,
  120. states={'draft': [('readonly', False)]})
  121. gender = fields.Selection([('male', _('Male')),
  122. ('female', _('Female')),
  123. ('other', _('Other'))],
  124. string='Gender',
  125. readonly=True,
  126. states={'draft': [('readonly', False)]})
  127. type = fields.Selection([('new', 'New Cooperator'),
  128. ('subscription', 'Subscription'),
  129. ('increase', 'Increase number of share')],
  130. string='Type', default="new",
  131. readonly=True,
  132. states={'draft': [('readonly', False)]})
  133. state = fields.Selection([('draft', 'Draft'),
  134. ('block', 'Blocked'),
  135. ('done', 'Done'),
  136. ('waiting', 'Waiting'),
  137. ('transfer', 'Transfer'),
  138. ('cancelled', 'Cancelled'),
  139. ('paid', 'paid')],
  140. string='State', required=True, default="draft")
  141. email = fields.Char(string='Email',
  142. required=True,
  143. readonly=True,
  144. states={'draft': [('readonly', False)]})
  145. iban = fields.Char(string='Account Number',
  146. readonly=True,
  147. states={'draft': [('readonly', False)]})
  148. partner_id = fields.Many2one('res.partner',
  149. string='Cooperator',
  150. readonly=True,
  151. states={'draft': [('readonly', False)]})
  152. share_product_id = fields.Many2one('product.product',
  153. string='Share type',
  154. domain=[('is_share', '=', True)],
  155. required=True,
  156. readonly=True,
  157. states={'draft': [('readonly', False)]})
  158. share_short_name = fields.Char(related='share_product_id.short_name',
  159. string='Share type name',
  160. readonly=True,
  161. states={'draft': [('readonly', False)]})
  162. share_unit_price = fields.Float(related='share_product_id.list_price',
  163. string='Share price',
  164. readonly=True,
  165. states={'draft': [('readonly', False)]})
  166. subscription_amount = fields.Float(compute='_compute_subscription_amount',
  167. string='Subscription amount',
  168. readonly=True,
  169. states={'draft': [('readonly', False)]})
  170. ordered_parts = fields.Integer(string='Number of Share',
  171. required=True,
  172. readonly=True,
  173. default=1,
  174. states={'draft': [('readonly', False)]})
  175. address = fields.Char(string='Address',
  176. required=True,
  177. readonly=True,
  178. states={'draft': [('readonly', False)]})
  179. city = fields.Char(string='City',
  180. required=True,
  181. readonly=True,
  182. states={'draft': [('readonly', False)]})
  183. zip_code = fields.Char(string='Zip Code',
  184. required=True,
  185. readonly=True,
  186. states={'draft': [('readonly', False)]})
  187. country_id = fields.Many2one('res.country',
  188. string='Country',
  189. ondelete='restrict',
  190. required=True,
  191. readonly=True,
  192. states={'draft': [('readonly', False)]})
  193. phone = fields.Char(string='Phone',
  194. readonly=True,
  195. states={'draft': [('readonly', False)]})
  196. user_id = fields.Many2one('res.users',
  197. string='Responsible',
  198. readonly=True)
  199. validated = fields.Boolean(compute='_validated_lines',
  200. string='Valid Line?',
  201. readonly=True)
  202. skip_control_ng = fields.Boolean(string="Skip control",
  203. help="if this field is checked then no"
  204. " control will be done on the national"
  205. " register number and on the iban bank"
  206. " account. To be done in case of the id"
  207. " card is from abroad or in case of"
  208. " a passport")
  209. lang = fields.Selection(_lang_get,
  210. string='Language',
  211. required=True,
  212. readonly=True,
  213. states={'draft': [('readonly', False)]},
  214. default=lambda self: self.env['res.company']._company_default_get().default_lang_id.code)
  215. date = fields.Date(string='Subscription date request',
  216. required=True,
  217. readonly=True,
  218. states={'draft': [('readonly', False)]},
  219. default=lambda self: datetime.strftime(datetime.now(),
  220. '%Y-%m-%d'))
  221. company_id = fields.Many2one('res.company',
  222. string='Company',
  223. required=True,
  224. change_default=True,
  225. readonly=True,
  226. default=lambda self: self.env['res.company']._company_default_get())
  227. is_company = fields.Boolean(string='Is a company',
  228. readonly=True,
  229. states={'draft': [('readonly', False)]})
  230. is_operation = fields.Boolean(string='Is an operation',
  231. readonly=True,
  232. states={'draft': [('readonly', False)]})
  233. company_name = fields.Char(string="Company name",
  234. readonly=True,
  235. states={'draft': [('readonly', False)]})
  236. company_email = fields.Char(string="Company email",
  237. readonly=True,
  238. states={'draft': [('readonly', False)]})
  239. company_register_number = fields.Char(string='Company register number',
  240. readonly=True,
  241. states={'draft': [('readonly', False)]})
  242. company_type = fields.Selection([('', '')],
  243. string="Company type",
  244. readonly=True,
  245. states={'draft': [('readonly', False)]})
  246. same_address = fields.Boolean(string='Same address',
  247. readonly=True,
  248. states={'draft': [('readonly', False)]})
  249. activities_address = fields.Char(string='Activities address',
  250. readonly=True,
  251. states={'draft': [('readonly', False)]})
  252. activities_city = fields.Char(string='Activities city',
  253. readonly=True,
  254. states={'draft': [('readonly', False)]})
  255. activities_zip_code = fields.Char(string='Activities zip Code',
  256. readonly=True,
  257. states={'draft': [('readonly', False)]})
  258. activities_country_id = fields.Many2one('res.country',
  259. string='Activities country',
  260. ondelete='restrict',
  261. readonly=True,
  262. states={'draft': [('readonly', False)]})
  263. contact_person_function = fields.Char(string='Function',
  264. readonly=True,
  265. states={'draft': [('readonly', False)]})
  266. operation_request_id = fields.Many2one('operation.request',
  267. string="Operation Request",
  268. readonly=True,
  269. states={'draft': [('readonly', False)]})
  270. capital_release_request = fields.One2many('account.invoice',
  271. 'subscription_request',
  272. string='Capital release request',
  273. readonly=True,
  274. states={'draft': [('readonly', False)]})
  275. capital_release_request_date = fields.Date(string="Force the capital "
  276. "release request date",
  277. help="Keep empty to use the "
  278. "current date",
  279. copy=False,
  280. readonly=True,
  281. states={'draft': [('readonly', False)]})
  282. source = fields.Selection([('website', 'Website'),
  283. ('crm', 'CRM'),
  284. ('manual', 'Manual'),
  285. ('operation', 'Operation')],
  286. string="Source",
  287. default="website",
  288. readonly=True,
  289. states={'draft': [('readonly', False)]})
  290. data_policy_approved = fields.Boolean(
  291. string='Data Policy Approved',
  292. default=False,
  293. )
  294. internal_rules_approved = fields.Boolean(
  295. string='Approved Internal Rules',
  296. default=False,
  297. )
  298. _order = "id desc"
  299. def get_person_info(self, partner):
  300. self.firstname = partner.firstname
  301. self.name = partner.name
  302. self.lastname = partner.lastname
  303. self.email = partner.email
  304. self.birthdate = partner.birthdate_date
  305. self.gender = partner.gender
  306. self.address = partner.street
  307. self.city = partner.city
  308. self.zip_code = partner.zip
  309. self.country_id = partner.country_id
  310. self.phone = partner.phone
  311. self.lang = partner.lang
  312. @api.onchange('partner_id')
  313. def onchange_partner(self):
  314. partner = self.partner_id
  315. if partner:
  316. self.is_company = partner.is_company
  317. self.already_cooperator = partner.member
  318. if partner.bank_ids:
  319. self.iban = partner.bank_ids[0].acc_number
  320. if partner.member:
  321. self.type = 'increase'
  322. if partner.is_company:
  323. self.company_name = partner.name
  324. self.company_email = partner.email
  325. self.company_register_number = partner.company_register_number
  326. representative = partner.get_representative()
  327. self.get_person_info(representative)
  328. self.contact_person_function = representative.function
  329. else:
  330. self.get_person_info(partner)
  331. # declare this function in order to be overriden
  332. def get_eater_vals(self, partner, share_product_id): #noqa
  333. return {}
  334. def _prepare_invoice_line(self, product, partner, qty):
  335. self.ensure_one()
  336. account = product.property_account_income_id \
  337. or product.categ_id.property_account_income_categ_id
  338. if not account:
  339. raise UserError(_('Please define income account for this product:'
  340. ' "%s" (id:%d) - or for its category: "%s".') %
  341. (product.name, product.id, product.categ_id.name))
  342. fpos = partner.property_account_position_id
  343. if fpos:
  344. account = fpos.map_account(account)
  345. res = {
  346. 'name': product.name,
  347. 'account_id': account.id,
  348. 'price_unit': product.lst_price,
  349. 'quantity': qty,
  350. 'uom_id': product.uom_id.id,
  351. 'product_id': product.id or False,
  352. }
  353. return res
  354. def send_capital_release_request(self, invoice):
  355. email_template = self.env.ref('email_template_release_capital', False)
  356. # we send the email with the capital release request in attachment
  357. # TODO remove sudo() and give necessary access right
  358. email_template.sudo().send_mail(invoice.id, True)
  359. invoice.sent = True
  360. def get_journal(self):
  361. return self.env['account.journal'].search([('code', '=', 'SUBJ')])[0]
  362. def get_accounting_account(self):
  363. account_obj = self.env['account.account']
  364. if self.company_id.property_cooperator_account:
  365. account = self.company_id.property_cooperator_account
  366. else:
  367. account = account_obj.search([('code', '=', '416000')])[0]
  368. return account
  369. def get_invoice_vals(self, partner):
  370. return {
  371. 'partner_id': partner.id,
  372. 'journal_id': self.get_journal().id,
  373. 'account_id': self.get_accounting_account().id,
  374. 'type': 'out_invoice',
  375. 'release_capital_request': True,
  376. 'subscription_request': self.id
  377. }
  378. def create_invoice(self, partner):
  379. # creating invoice and invoice lines
  380. invoice_vals = self.get_invoice_vals(partner)
  381. if self.capital_release_request_date:
  382. invoice_vals['date_invoice'] = self.capital_release_request_date
  383. invoice = self.env['account.invoice'].create(invoice_vals)
  384. vals = self._prepare_invoice_line(self.share_product_id, partner,
  385. self.ordered_parts)
  386. vals['invoice_id'] = invoice.id
  387. self.env['account.invoice.line'].create(vals)
  388. # validate the capital release request
  389. invoice.action_invoice_open()
  390. self.send_capital_release_request(invoice)
  391. return invoice
  392. def get_partner_company_vals(self):
  393. partner_vals = {'name': self.company_name,
  394. 'last_name': self.company_name,
  395. 'is_company': self.is_company,
  396. 'company_register_number': self.company_register_number, #noqa
  397. 'customer': False, 'cooperator': True,
  398. 'street': self.address, 'zip': self.zip_code,
  399. 'city': self.city, 'email': self.company_email,
  400. 'out_inv_comm_type': 'bba',
  401. 'customer': self.share_product_id.customer,
  402. 'out_inv_comm_algorithm': 'random',
  403. 'country_id': self.country_id.id,
  404. 'lang': self.lang,
  405. 'data_policy_approved': self.data_policy_approved,
  406. 'internal_rules_approved': self.internal_rules_approved
  407. }
  408. return partner_vals
  409. def get_partner_vals(self):
  410. partner_vals = {'name': self.name, 'firstname': self.firstname,
  411. 'lastname': self.lastname, 'street': self.address,
  412. 'zip': self.zip_code, 'email': self.email,
  413. 'gender': self.gender, 'cooperator': True,
  414. 'city': self.city, 'phone': self.phone,
  415. 'out_inv_comm_type': 'bba',
  416. 'out_inv_comm_algorithm': 'random',
  417. 'country_id': self.country_id.id, 'lang': self.lang,
  418. 'birthdate_date': self.birthdate,
  419. 'customer': self.share_product_id.customer,
  420. 'data_policy_approved': self.data_policy_approved,
  421. 'internal_rules_approved': self.internal_rules_approved
  422. }
  423. return partner_vals
  424. def create_coop_partner(self):
  425. partner_obj = self.env['res.partner']
  426. if self.is_company:
  427. partner_vals = self.get_partner_company_vals()
  428. else:
  429. partner_vals = self.get_partner_vals()
  430. partner = partner_obj.create(partner_vals)
  431. if self.iban:
  432. self.env['res.partner.bank'].create({
  433. 'partner_id': partner.id,
  434. 'acc_number': self.iban
  435. })
  436. return partner
  437. def set_membership(self):
  438. # To be overridden
  439. return True
  440. @api.one
  441. def validate_subscription_request(self):
  442. partner_obj = self.env['res.partner']
  443. if self.ordered_parts <= 0:
  444. raise UserError(_('Number of share must be greater than 0.'))
  445. if self.partner_id:
  446. if not self.partner_id.cooperator:
  447. self.partner_id.cooperator = True
  448. partner = self.partner_id
  449. else:
  450. partner = None
  451. domain = []
  452. if self.already_cooperator:
  453. raise UserError(_('The checkbox already cooperator is'
  454. ' checked please select a cooperator.'))
  455. elif self.is_company and self.company_register_number:
  456. domain = [('company_register_number', '=', self.company_register_number)] #noqa
  457. elif not self.is_company and self.email:
  458. domain = [('email', '=', self.email)]
  459. if domain:
  460. partner = partner_obj.search(domain)
  461. if not partner:
  462. partner = self.create_coop_partner()
  463. else:
  464. partner = partner[0]
  465. if self.is_company and not partner.has_representative():
  466. contact = False
  467. if self.email:
  468. domain = [('email', '=', self.email)]
  469. contact = partner_obj.search(domain)
  470. if contact:
  471. contact.type = 'representative'
  472. if not contact:
  473. contact_vals = {'name': self.name,
  474. 'firstname': self.firstname,
  475. 'lastname': self.lastname, 'customer': False,
  476. 'is_company': False, 'cooperator': True,
  477. 'street': self.address, 'gender': self.gender,
  478. 'zip': self.zip_code, 'city': self.city,
  479. 'phone': self.phone, 'email': self.email,
  480. 'country_id': self.country_id.id,
  481. 'out_inv_comm_type': 'bba',
  482. 'out_inv_comm_algorithm': 'random',
  483. 'lang': self.lang,
  484. 'birthdate_date': self.birthdate,
  485. 'parent_id': partner.id,
  486. 'representative': True,
  487. 'function': self.contact_person_function,
  488. 'type': 'representative',
  489. 'data_policy_approved': self.data_policy_approved,
  490. 'internal_rules_approved': self.internal_rules_approved
  491. }
  492. contact = partner_obj.create(contact_vals)
  493. else:
  494. if len(contact) > 1:
  495. raise UserError(_('There is two different persons with the'
  496. ' same national register number. Please'
  497. ' proceed to a merge before to continue')
  498. )
  499. if contact.parent_id and contact.parent_id.id != partner.id:
  500. raise UserError(_('This contact person is already defined'
  501. ' for another company. Please select'
  502. ' another contact'))
  503. else:
  504. contact.write({'parent_id': partner.id,
  505. 'representative': True})
  506. invoice = self.create_invoice(partner)
  507. self.write({'partner_id': partner.id, 'state': 'done'})
  508. self.set_membership()
  509. return invoice
  510. @api.one
  511. def block_subscription_request(self):
  512. self.write({'state': 'block'})
  513. @api.one
  514. def unblock_subscription_request(self):
  515. self.write({'state': 'draft'})
  516. @api.one
  517. def cancel_subscription_request(self):
  518. self.write({'state': 'cancelled'})
  519. @api.one
  520. def put_on_waiting_list(self):
  521. self.write({'state': 'waiting'})
  522. class ShareLine(models.Model):
  523. _name = 'share.line'
  524. _description = "Share line"
  525. @api.multi
  526. def _compute_total_line(self):
  527. res = {}
  528. for line in self:
  529. line.total_amount_line = line.share_unit_price * line.share_number
  530. return res
  531. share_product_id = fields.Many2one('product.product',
  532. string='Share type',
  533. required=True,
  534. readonly=True)
  535. share_number = fields.Integer(string='Number of Share',
  536. required=True,
  537. readonly=True)
  538. share_short_name = fields.Char(related='share_product_id.short_name',
  539. string='Share type name',
  540. readonly=True)
  541. share_unit_price = fields.Float(string='Share price',
  542. readonly=True)
  543. effective_date = fields.Date(string='Effective Date',
  544. readonly=True)
  545. partner_id = fields.Many2one('res.partner',
  546. string='Cooperator',
  547. required=True,
  548. ondelete='cascade',
  549. readonly=True)
  550. total_amount_line = fields.Float(compute='_compute_total_line',
  551. string='Total amount line')
  552. class SubscriptionRegister(models.Model):
  553. _name = 'subscription.register'
  554. _description = "Subscription register"
  555. @api.multi
  556. def _compute_total_line(self):
  557. for register_line in self:
  558. register_line.total_amount_line = register_line.share_unit_price * register_line.quantity
  559. name = fields.Char(string='Number Operation',
  560. required=True,
  561. readonly=True)
  562. register_number_operation = fields.Integer(string='Register Number Operation',
  563. required=True,
  564. readonly=True)
  565. partner_id = fields.Many2one('res.partner',
  566. string='Cooperator',
  567. required=True,
  568. readonly=True)
  569. partner_id_to = fields.Many2one('res.partner',
  570. string='Transfered to',
  571. readonly=True)
  572. date = fields.Date(string='Subscription Date',
  573. required=True,
  574. readonly=True)
  575. quantity = fields.Integer(string='Number of share',
  576. readonly=True)
  577. share_unit_price = fields.Float(string='Share price',
  578. readonly=True)
  579. total_amount_line = fields.Float(compute='_compute_total_line',
  580. string='Total amount line')
  581. share_product_id = fields.Many2one('product.product',
  582. string='Share type',
  583. required=True,
  584. readonly=True,
  585. domain=[('is_share', '=', True)])
  586. share_short_name = fields.Char(related='share_product_id.short_name',
  587. string='Share type name',
  588. readonly=True)
  589. share_to_product_id = fields.Many2one('product.product',
  590. string='Share to type',
  591. readonly=True,
  592. domain=[('is_share', '=', True)])
  593. share_to_short_name = fields.Char(related='share_to_product_id.short_name',
  594. string='Share to type name',
  595. readonly=True)
  596. quantity_to = fields.Integer(string='Number of share to',
  597. readonly=True)
  598. share_to_unit_price = fields.Float(string='Share to price',
  599. readonly=True)
  600. type = fields.Selection([('subscription', 'Subscription'),
  601. ('transfer', 'Transfer'),
  602. ('sell_back', 'Sell Back'),
  603. ('convert', 'Conversion')],
  604. string='Operation Type', readonly=True)
  605. company_id = fields.Many2one('res.company', string='Company',
  606. required=True,
  607. change_default=True, readonly=True,
  608. default=lambda self: self.env['res.company']._company_default_get())
  609. user_id = fields.Many2one('res.users',
  610. string='Responsible',
  611. readonly=True,
  612. default=lambda self: self.env.user)
  613. _order = "register_number_operation asc"
  614. @api.model
  615. def read_group(self, domain, fields, groupby, offset=0, limit=None,
  616. orderby=False,
  617. lazy=True):
  618. if 'share_unit_price' in fields:
  619. fields.remove('share_unit_price')
  620. if 'register_number_operation' in fields:
  621. fields.remove('register_number_operation')
  622. res = super(SubscriptionRegister, self).read_group(domain, fields,
  623. groupby,
  624. offset=offset,
  625. limit=limit,
  626. orderby=orderby,
  627. lazy=lazy)
  628. if 'total_amount_line' in fields:
  629. for line in res:
  630. if '__domain' in line:
  631. lines = self.search(line['__domain'])
  632. inv_value = 0.0
  633. for line2 in lines:
  634. inv_value += line2.total_amount_line
  635. line['total_amount_line'] = inv_value
  636. return res