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.

683 lines
32 KiB

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