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.

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