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.

690 lines
33 KiB

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