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.

578 lines
26 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 not sub_request.is_company:
  99. if sub_request.skip_control_ng \
  100. or self.check_belgian_identification_id(
  101. sub_request.no_registre):
  102. validated = True
  103. else:
  104. validated = False
  105. sub_request.validated = validated
  106. @api.multi
  107. @api.depends('share_product_id',
  108. 'share_product_id.list_price',
  109. 'ordered_parts')
  110. def _compute_subscription_amount(self):
  111. for sub_request in self:
  112. sub_request.subscription_amount = sub_request.share_product_id.list_price * sub_request.ordered_parts
  113. already_cooperator = fields.Boolean(string="I'm already cooperator")
  114. name = fields.Char(string='Name',
  115. required=True)
  116. firstname = fields.Char(string='Firstname')
  117. lastname = fields.Char(string='Lastname')
  118. birthdate = fields.Date(string="Birthdate")
  119. gender = fields.Selection([('male', _('Male')),
  120. ('female', _('Female')),
  121. ('other', _('Other'))], string='Gender')
  122. type = fields.Selection([('new', 'New Cooperator'),
  123. ('subscription', 'Subscription'),
  124. ('increase', 'Increase number of share')],
  125. string='Type', default="new")
  126. state = fields.Selection([('draft', 'Draft'),
  127. ('block', 'Blocked'),
  128. ('done', 'Done'),
  129. ('waiting', 'Waiting'),
  130. ('transfer', 'Transfer'),
  131. ('cancelled', 'Cancelled'),
  132. ('paid', 'paid')],
  133. string='State', required=True, default="draft")
  134. email = fields.Char(string='Email', required=True)
  135. iban = fields.Char(string='Account Number')
  136. partner_id = fields.Many2one('res.partner',
  137. string='Cooperator')
  138. share_product_id = fields.Many2one('product.product',
  139. string='Share type',
  140. domain=[('is_share', '=', True)],
  141. required=True)
  142. share_short_name = fields.Char(related='share_product_id.short_name',
  143. string='Share type name')
  144. share_unit_price = fields.Float(related='share_product_id.list_price',
  145. string='Share price')
  146. subscription_amount = fields.Float(compute='_compute_subscription_amount',
  147. string='Subscription amount')
  148. ordered_parts = fields.Integer(string='Number of Share',
  149. required=True)
  150. address = fields.Char(string='Address',
  151. required=True)
  152. city = fields.Char(string='City',
  153. required=True)
  154. zip_code = fields.Char(string='Zip Code',
  155. required=True)
  156. country_id = fields.Many2one('res.country',
  157. string='Country',
  158. ondelete='restrict',
  159. required=True)
  160. phone = fields.Char(string='Phone')
  161. no_registre = fields.Char(string='National Register Number')
  162. user_id = fields.Many2one('res.users',
  163. string='Responsible',
  164. readonly=True)
  165. validated = fields.Boolean(compute='_validated_lines',
  166. string='Valid Line?',
  167. readonly=True)
  168. skip_control_ng = fields.Boolean(string="Skip control",
  169. help="if this field is checked then no"
  170. " control will be done on the national"
  171. " register number and on the iban bank"
  172. " account. To be done in case of the id"
  173. " card is from abroad or in case of"
  174. " a passport")
  175. lang = fields.Selection(_lang_get,
  176. string='Language',
  177. required=True,
  178. default=lambda self: self.env['res.company']._company_default_get().default_lang_id.code)
  179. date = fields.Date(string='Subscription date request',
  180. required=True,
  181. default=lambda self: datetime.strftime(datetime.now(), '%Y-%m-%d'))
  182. company_id = fields.Many2one('res.company', string='Company', required=True,
  183. change_default=True,
  184. readonly=True,
  185. default=lambda self: self.env['res.company']._company_default_get())
  186. is_company = fields.Boolean(string='Is a company')
  187. is_operation = fields.Boolean(string='Is an operation')
  188. company_name = fields.Char(string="Company name")
  189. company_email = fields.Char(string="Company email")
  190. company_register_number = fields.Char(string='Company register number')
  191. company_type = fields.Selection([('scrl', 'SCRL'),
  192. ('asbl', 'ASBL'),
  193. ('sprl', 'SPRL'),
  194. ('sa', 'SA'),
  195. ('other', 'Other')])
  196. same_address = fields.Boolean(string='Same address')
  197. activities_address = fields.Char(string='Activities address')
  198. activities_city = fields.Char(string='Activities city')
  199. activities_zip_code = fields.Char(string='Activities zip Code')
  200. activities_country_id = fields.Many2one('res.country',
  201. string='Activities country',
  202. ondelete='restrict')
  203. contact_person_function = fields.Char(string='Function')
  204. operation_request_id = fields.Many2one('operation.request',
  205. string="Operation Request")
  206. is_operation = fields.Boolean(string="Is Operation request")
  207. capital_release_request = fields.One2many('account.invoice',
  208. 'subscription_request',
  209. string='Capital release request',
  210. readonly=True)
  211. capital_release_request_date = fields.Date(string="Force the capital release request date",
  212. help="Keep empty to use the current date",
  213. copy=False)
  214. source = fields.Selection([('website', 'Website'),
  215. ('crm', 'CRM'),
  216. ('manual', 'Manual'),
  217. ('operation', 'Operation')],
  218. string="Source",
  219. default="website")
  220. _order = "id desc"
  221. # declare this function in order to be overriden
  222. def get_eater_vals(self, partner, share_product_id):
  223. return {}
  224. def _prepare_invoice_line(self, product, partner, qty):
  225. self.ensure_one()
  226. account = product.property_account_income_id \
  227. or product.categ_id.property_account_income_categ_id
  228. if not account:
  229. raise UserError(_('Please define income account for this product:'
  230. ' "%s" (id:%d) - or for its category: "%s".') %
  231. (product.name, product.id, product.categ_id.name))
  232. fpos = partner.property_account_position_id
  233. if fpos:
  234. account = fpos.map_account(account)
  235. res = {
  236. 'name': product.name,
  237. 'account_id': account.id,
  238. 'price_unit': product.lst_price,
  239. 'quantity': qty,
  240. 'uom_id': product.uom_id.id,
  241. 'product_id': product.id or False,
  242. }
  243. return res
  244. def send_capital_release_request(self, invoice):
  245. invoice_email_template = self.env['mail.template'].search([('name', '=', 'Request to Release Capital - Send by Email')])[0]
  246. # we send the email with the capital release request in attachment
  247. invoice_email_template.send_mail(invoice.id, True)
  248. invoice.sent = True
  249. def create_invoice(self, partner):
  250. # get subscription journal
  251. journal = self.env['account.journal'].search([('code', '=', 'SUBJ')])[0]
  252. # get the account for associate
  253. # TODO this should be defined in configuration
  254. if self.company_id.property_cooperator_account:
  255. account = self.company_id.property_cooperator_account
  256. else:
  257. account = self.env['account.account'].search([('code', '=', '416000')])[0]
  258. # creating invoice and invoice lines
  259. invoice_vals = {'partner_id': partner.id,
  260. 'journal_id': journal.id,
  261. 'account_id': account.id,
  262. 'type': 'out_invoice',
  263. 'release_capital_request': True,
  264. 'subscription_request': self.id}
  265. if self.capital_release_request_date:
  266. invoice_vals['date_invoice'] = self.capital_release_request_date
  267. invoice = self.env['account.invoice'].create(invoice_vals)
  268. vals = self._prepare_invoice_line(self.share_product_id, partner,
  269. self.ordered_parts)
  270. vals['invoice_id'] = invoice.id
  271. self.env['account.invoice.line'].create(vals)
  272. # validate the capital release request
  273. invoice.signal_workflow('invoice_open')
  274. self.send_capital_release_request(invoice)
  275. return invoice
  276. def get_partner_company_vals(self):
  277. partner_vals = {'name': self.company_name,
  278. 'last_name': self.company_name,
  279. 'is_company': self.is_company,
  280. 'company_register_number': self.company_register_number,
  281. 'customer': False, 'cooperator': True,
  282. 'street': self.address, 'zip': self.zip_code,
  283. 'city': self.city, 'email': self.company_email,
  284. 'out_inv_comm_type': 'bba',
  285. 'customer': self.share_product_id.customer,
  286. 'out_inv_comm_algorithm': 'random',
  287. 'country_id': self.country_id.id,
  288. 'lang': self.lang}
  289. return partner_vals
  290. def get_partner_vals(self):
  291. partner_vals = {'name': self.name, 'first_name': self.firstname,
  292. 'last_name': self.lastname, 'street': self.address,
  293. 'zip': self.zip_code, 'email': self.email,
  294. 'gender': self.gender, 'cooperator': True,
  295. 'city': self.city, 'phone': self.phone,
  296. 'national_register_number': self.no_registre,
  297. 'out_inv_comm_type': 'bba',
  298. 'out_inv_comm_algorithm': 'random',
  299. 'country_id': self.country_id.id, 'lang': self.lang,
  300. 'birthdate_date': self.birthdate,
  301. 'customer': self.share_product_id.customer}
  302. return partner_vals
  303. def create_coop_partner(self):
  304. partner_obj = self.env['res.partner']
  305. if self.is_company:
  306. partner_vals = self.get_partner_company_vals()
  307. else:
  308. partner_vals = self.get_partner_vals()
  309. partner = partner_obj.create(partner_vals)
  310. if self.iban:
  311. self.env['res.partner.bank'].create({
  312. 'partner_id': partner.id,
  313. 'acc_number': self.iban
  314. })
  315. return partner
  316. def create_user(self, partner):
  317. user_obj = self.env['res.users']
  318. # TODO replace self by partner
  319. email = self.email
  320. if self.is_company:
  321. email = self.company_email
  322. user = user_obj.search([('login', '=', email)])
  323. if not user:
  324. user_values = {'partner_id': partner.id, 'login': email}
  325. user_id = user_obj.sudo()._signup_create_user(user_values)
  326. user = user_obj.browse(user_id)
  327. user.sudo().with_context({'create_user': True}).action_reset_password()
  328. return True
  329. @api.one
  330. def validate_subscription_request(self):
  331. partner_obj = self.env['res.partner']
  332. if self.ordered_parts <= 0:
  333. raise UserError(_('Number of share must be greater than 0.'))
  334. if self.partner_id:
  335. if not self.partner_id.cooperator:
  336. self.partner_id.cooperator = True
  337. partner = self.partner_id
  338. else:
  339. if self.already_cooperator:
  340. raise UserError(_('The checkbox already cooperator is'
  341. ' checked please select a cooperator.'))
  342. elif self.is_company and self.company_register_number:
  343. partner = partner_obj.search([('company_register_number', '=', self.company_register_number)])
  344. elif self.no_registre:
  345. partner = partner_obj.search([('national_register_number', '=', self.no_registre)])
  346. else:
  347. partner = None
  348. if not partner:
  349. partner = self.create_coop_partner()
  350. else:
  351. partner = partner[0]
  352. if self.is_company and not partner.has_representative():
  353. contact = False
  354. if self.no_registre:
  355. contact = partner_obj.search([('national_register_number', '=', self.no_registre)])
  356. if contact:
  357. contact.type = 'representative'
  358. if not contact:
  359. contact_vals = {'name': self.name,
  360. 'first_name': self.firstname,
  361. 'last_name': self.lastname, 'customer': False,
  362. 'is_company': False, 'cooperator': True,
  363. 'street': self.address, 'gender': self.gender,
  364. 'zip': self.zip_code, 'city': self.city,
  365. 'phone': self.phone, 'email': self.email,
  366. 'national_register_number': self.no_registre,
  367. 'country_id': self.country_id.id,
  368. 'out_inv_comm_type': 'bba',
  369. 'out_inv_comm_algorithm': 'random',
  370. 'lang': self.lang,
  371. 'birthdate_date': self.birthdate,
  372. 'parent_id': partner.id,
  373. 'representative': True,
  374. 'function': self.contact_person_function,
  375. 'type': 'representative'}
  376. contact = partner_obj.create(contact_vals)
  377. else:
  378. if len(contact) > 1:
  379. raise UserError(_('There is two different persons with the'
  380. ' same national register number. Please'
  381. ' proceed to a merge before to continue')
  382. )
  383. if contact.parent_id and contact.parent_id.id != partner.id:
  384. raise UserError(_('This contact person is already defined'
  385. ' for another company. Please select'
  386. ' another contact'))
  387. else:
  388. contact.write({'parent_id': partner.id,
  389. 'representative': True})
  390. invoice = self.create_invoice(partner)
  391. self.write({'partner_id': partner.id, 'state': 'done'})
  392. self.create_user(partner)
  393. return invoice
  394. @api.one
  395. def block_subscription_request(self):
  396. self.write({'state': 'block'})
  397. @api.one
  398. def unblock_subscription_request(self):
  399. self.write({'state': 'draft'})
  400. @api.one
  401. def cancel_subscription_request(self):
  402. self.write({'state': 'cancelled'})
  403. @api.one
  404. def put_on_waiting_list(self):
  405. self.write({'state': 'waiting'})
  406. class share_line(models.Model):
  407. _name = 'share.line'
  408. @api.multi
  409. def _compute_total_line(self):
  410. res = {}
  411. for line in self:
  412. line.total_amount_line = line.share_unit_price * line.share_number
  413. return res
  414. share_product_id = fields.Many2one('product.product',
  415. string='Share type',
  416. required=True,
  417. readonly=True)
  418. share_number = fields.Integer(string='Number of Share',
  419. required=True,
  420. readonly=True)
  421. share_short_name = fields.Char(related='share_product_id.short_name',
  422. string='Share type name')
  423. share_unit_price = fields.Float(string='Share price',
  424. readonly=True)
  425. effective_date = fields.Date(string='Effective Date',
  426. readonly=True)
  427. partner_id = fields.Many2one('res.partner',
  428. string='Cooperator',
  429. required=True,
  430. ondelete='cascade',
  431. readonly=True)
  432. total_amount_line = fields.Float(compute='_compute_total_line',
  433. string='Total amount line')
  434. class subscription_register(models.Model):
  435. _name = 'subscription.register'
  436. @api.multi
  437. def _compute_total_line(self):
  438. for register_line in self:
  439. register_line.total_amount_line = register_line.share_unit_price * register_line.quantity
  440. name = fields.Char(string='Register Number Operation',
  441. required=True,
  442. readonly=True)
  443. register_number_operation = fields.Integer(string='Register Number Operation',
  444. required=True,
  445. readonly=True)
  446. partner_id = fields.Many2one('res.partner',
  447. string='Cooperator',
  448. required=True,
  449. readonly=True)
  450. partner_id_to = fields.Many2one('res.partner',
  451. string='Transfered to',
  452. readonly=True)
  453. date = fields.Date(string='Subscription Date',
  454. required=True,
  455. readonly=True)
  456. quantity = fields.Integer(string='Number of share',
  457. readonly=True)
  458. share_unit_price = fields.Float(string='Share price',
  459. readonly=True)
  460. total_amount_line = fields.Float(compute='_compute_total_line',
  461. string='Total amount line')
  462. share_product_id = fields.Many2one('product.product',
  463. string='Share type',
  464. required=True,
  465. readonly=True,
  466. domain=[('is_share', '=', True)])
  467. share_short_name = fields.Char(related='share_product_id.short_name',
  468. string='Share type name',
  469. readonly=True)
  470. share_to_product_id = fields.Many2one('product.product',
  471. string='Share to type',
  472. readonly=True,
  473. domain=[('is_share', '=', True)])
  474. share_to_short_name = fields.Char(related='share_to_product_id.short_name',
  475. string='Share to type name',
  476. readonly=True)
  477. quantity_to = fields.Integer(string='Number of share to',
  478. readonly=True)
  479. share_to_unit_price = fields.Float(string='Share to price',
  480. readonly=True)
  481. type = fields.Selection([('subscription', 'Subscription'),
  482. ('transfer', 'Transfer'),
  483. ('sell_back', 'Sell Back'),
  484. ('convert', 'Conversion')],
  485. string='Operation Type', readonly=True)
  486. company_id = fields.Many2one('res.company', string='Company',
  487. required=True,
  488. change_default=True, readonly=True,
  489. default=lambda self: self.env['res.company']._company_default_get())
  490. user_id = fields.Many2one('res.users',
  491. string='Responsible',
  492. readonly=True,
  493. default=lambda self: self.env.user)
  494. _order = "register_number_operation asc"
  495. @api.model
  496. def read_group(self, domain, fields, groupby, offset=0, limit=None,
  497. orderby=False,
  498. lazy=True):
  499. if 'share_unit_price' in fields:
  500. fields.remove('share_unit_price')
  501. if 'register_number_operation' in fields:
  502. fields.remove('register_number_operation')
  503. res = super(subscription_register, self).read_group(domain, fields,
  504. groupby,
  505. offset=offset,
  506. limit=limit,
  507. orderby=orderby,
  508. lazy=lazy)
  509. if 'total_amount_line' in fields:
  510. for line in res:
  511. if '__domain' in line:
  512. lines = self.search(line['__domain'])
  513. inv_value = 0.0
  514. for line2 in lines:
  515. inv_value += line2.total_amount_line
  516. line['total_amount_line'] = inv_value
  517. return res