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.

495 lines
17 KiB

[ADD] bond and loan issues management [ADD] bond and loan issues management module skeleton [IMP] change increase menu sequence [IMP] add models, fields and views [IMP] add xml declaration in head of file [ADD] add easy_my_coop_loan_website - WIP [IMP] add access rights [IMP] this raise inconsistency so replace id by default_code. [IMP] change import openerp to odoo [IMP] add website loan module [FIX] put website display in loan [FIX] fix import [FIX] fix function [IMP] use correct name [IMP] make the loan and bond visible [IMP] add js, field and logic to set amount limit per subscription [IMP] remove dependency on recaptcha as user is logged to subscribe [IMP] add fields [IMP] save loan issue subscription still in WIP [IMP] remove alert pop up [IMP] add dependency to easy_my_coop_website [IMP] remove force send for sub request creation email notification [IMP] add mail templates [IMP] save subscription in the corresponding loan issue. add email notif [FIX] fix loan issue line view [FIX] add related field to loan issue. It is where the data stand [IMP] move term_view up [FIX] fix js error when false is returned [FIX] fix function when loan_issue_id in None [IMP] add actions and button [FIX] fix action [FIX] fix mail template [IMP] set noupdate=1 [IMP] change order [IMP] display loan issue lines on partner form [IMP] add loan view in partner form [IMP] add face value on loan issue and line add face value on loan issue and line. add as well the quantity and computation of the amount [FIX] missing id overriding values wasn't working [IMP] getting bond face value and setting it as step. [IMP] subscribed_amount computed field is the sum of the amount lines [IMP] allow a waiting payment to be cancelled [IMP] make field required [REFACT] move loan issue line code to dedicated file [IMP] add interest calculation and model [ADD] bond and loan issues management module skeleton [IMP] add models, fields and views [IMP] allow creation by hand [IMP] adding partner related field [IMP] put code in separate function [FIX] pass it to get method [IMP] routes consistent form [FIX] fix eof [FIX] GET is working for ajax call [IMP] website page for loan issue subscription
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
[ADD] bond and loan issues management [ADD] bond and loan issues management module skeleton [IMP] change increase menu sequence [IMP] add models, fields and views [IMP] add xml declaration in head of file [ADD] add easy_my_coop_loan_website - WIP [IMP] add access rights [IMP] this raise inconsistency so replace id by default_code. [IMP] change import openerp to odoo [IMP] add website loan module [FIX] put website display in loan [FIX] fix import [FIX] fix function [IMP] use correct name [IMP] make the loan and bond visible [IMP] add js, field and logic to set amount limit per subscription [IMP] remove dependency on recaptcha as user is logged to subscribe [IMP] add fields [IMP] save loan issue subscription still in WIP [IMP] remove alert pop up [IMP] add dependency to easy_my_coop_website [IMP] remove force send for sub request creation email notification [IMP] add mail templates [IMP] save subscription in the corresponding loan issue. add email notif [FIX] fix loan issue line view [FIX] add related field to loan issue. It is where the data stand [IMP] move term_view up [FIX] fix js error when false is returned [FIX] fix function when loan_issue_id in None [IMP] add actions and button [FIX] fix action [FIX] fix mail template [IMP] set noupdate=1 [IMP] change order [IMP] display loan issue lines on partner form [IMP] add loan view in partner form [IMP] add face value on loan issue and line add face value on loan issue and line. add as well the quantity and computation of the amount [FIX] missing id overriding values wasn't working [IMP] getting bond face value and setting it as step. [IMP] subscribed_amount computed field is the sum of the amount lines [IMP] allow a waiting payment to be cancelled [IMP] make field required [REFACT] move loan issue line code to dedicated file [IMP] add interest calculation and model [ADD] bond and loan issues management module skeleton [IMP] add models, fields and views [IMP] allow creation by hand [IMP] adding partner related field [IMP] put code in separate function [FIX] pass it to get method [IMP] routes consistent form [FIX] fix eof [FIX] GET is working for ajax call [IMP] website page for loan issue subscription
5 years ago
5 years ago
5 years ago
  1. import base64
  2. import re
  3. from datetime import datetime
  4. from odoo import http
  5. from odoo.http import request
  6. from odoo.tools.translate import _
  7. # Only use for behavior, don't stock it
  8. _TECHNICAL = [
  9. "view_from",
  10. "view_callback"
  11. ]
  12. # transient fields used to compute the address field
  13. _EXTRA_FIELDS = [
  14. "street_name",
  15. "house_number"
  16. ]
  17. # Allow in description
  18. _BLACKLIST = [
  19. "id",
  20. "create_uid",
  21. "create_date",
  22. "write_uid",
  23. "write_date",
  24. "user_id",
  25. "active",
  26. ]
  27. _COOP_FORM_FIELD = [
  28. "email",
  29. "confirm_email",
  30. "firstname",
  31. "lastname",
  32. "birthdate",
  33. "iban",
  34. "share_product_id",
  35. "street_name",
  36. "house_number",
  37. "city",
  38. "zip_code",
  39. "country_id",
  40. "phone",
  41. "lang",
  42. "nb_parts",
  43. "total_parts",
  44. "error_msg",
  45. ]
  46. _COMPANY_FORM_FIELD = [
  47. "is_company",
  48. "company_register_number",
  49. "company_name",
  50. "company_email",
  51. "confirm_email",
  52. "email",
  53. "firstname",
  54. "lastname",
  55. "birthdate",
  56. "iban",
  57. "share_product_id",
  58. "street_name",
  59. "house_number",
  60. "city",
  61. "zip_code",
  62. "country_id",
  63. "phone",
  64. "lang",
  65. "nb_parts",
  66. "total_parts",
  67. "error_msg",
  68. "company_type",
  69. ]
  70. class WebsiteSubscription(http.Controller):
  71. @http.route(
  72. ["/page/become_cooperator", "/become_cooperator"],
  73. type="http",
  74. auth="public",
  75. website=True,
  76. )
  77. def display_become_cooperator_page(self, **kwargs):
  78. values = {}
  79. logged = False
  80. if request.env.user.login != "public":
  81. logged = True
  82. partner = request.env.user.partner_id
  83. if partner.is_company:
  84. return self.display_become_company_cooperator_page()
  85. values = self.fill_values(values, False, logged, True)
  86. for field in _COOP_FORM_FIELD:
  87. if kwargs.get(field):
  88. values[field] = kwargs.pop(field)
  89. values.update(kwargs=kwargs.items())
  90. return request.render("easy_my_coop_website.becomecooperator", values)
  91. @http.route(
  92. ["/page/become_company_cooperator", "/become_company_cooperator"],
  93. type="http",
  94. auth="public",
  95. website=True,
  96. )
  97. def display_become_company_cooperator_page(self, **kwargs):
  98. values = {}
  99. logged = False
  100. if request.env.user.login != "public":
  101. logged = True
  102. values = self.fill_values(values, True, logged, True)
  103. for field in _COMPANY_FORM_FIELD:
  104. if kwargs.get(field):
  105. values[field] = kwargs.pop(field)
  106. values.update(kwargs=kwargs.items())
  107. return request.render(
  108. "easy_my_coop_website.becomecompanycooperator", values
  109. )
  110. def preRenderThanks(self, values, kwargs):
  111. """ Allow to be overrided """
  112. return {"_values": values, "_kwargs": kwargs}
  113. def get_subscription_response(self, values, kwargs):
  114. values = self.preRenderThanks(values, kwargs)
  115. return request.render("easy_my_coop_website.cooperator_thanks", values)
  116. def get_date_string(self, birthdate):
  117. if birthdate:
  118. return datetime.strftime(birthdate, "%d/%m/%Y")
  119. return False
  120. def get_values_from_user(self, values, is_company):
  121. # the subscriber is connected
  122. if request.env.user.login != "public":
  123. values["logged"] = "on"
  124. partner = request.env.user.partner_id
  125. if partner.member or partner.old_member:
  126. values["already_cooperator"] = "on"
  127. if partner.bank_ids:
  128. values["iban"] = partner.bank_ids[0].acc_number
  129. values["address"] = partner.street
  130. values["zip_code"] = partner.zip
  131. values["city"] = partner.city
  132. values["country_id"] = partner.country_id.id
  133. if is_company:
  134. # company values
  135. values[
  136. "company_register_number"
  137. ] = partner.company_register_number
  138. values["company_name"] = partner.name
  139. values["company_email"] = partner.email
  140. values["company_type"] = partner.legal_form
  141. # contact person values
  142. representative = partner.get_representative()
  143. values["firstname"] = representative.firstname
  144. values["lastname"] = representative.lastname
  145. values["gender"] = representative.gender
  146. values["email"] = representative.email
  147. values["contact_person_function"] = representative.function
  148. values["birthdate"] = self.get_date_string(
  149. representative.birthdate_date
  150. )
  151. values["lang"] = representative.lang
  152. values["phone"] = representative.phone
  153. else:
  154. values["firstname"] = partner.firstname
  155. values["lastname"] = partner.lastname
  156. values["email"] = partner.email
  157. values["gender"] = partner.gender
  158. values["birthdate"] = self.get_date_string(
  159. partner.birthdate_date
  160. )
  161. values["lang"] = partner.lang
  162. values["phone"] = partner.phone
  163. return values
  164. def fill_values(self, values, is_company, logged, load_from_user=False):
  165. sub_req_obj = request.env["subscription.request"]
  166. company = request.website.company_id
  167. products = self.get_products_share(is_company)
  168. if load_from_user:
  169. values = self.get_values_from_user(values, is_company)
  170. if is_company:
  171. values["is_company"] = "on"
  172. if logged:
  173. values["logged"] = "on"
  174. values["countries"] = self.get_countries()
  175. values["langs"] = self.get_langs()
  176. values["products"] = products
  177. fields_desc = sub_req_obj.sudo().fields_get(["company_type", "gender"])
  178. values["company_types"] = fields_desc["company_type"]["selection"]
  179. values["genders"] = fields_desc["gender"]["selection"]
  180. values["company"] = company
  181. if not values.get("share_product_id"):
  182. for product in products:
  183. if product.default_share_product is True:
  184. values["share_product_id"] = product.id
  185. break
  186. if not values.get("share_product_id", False) and products:
  187. values["share_product_id"] = products[0].id
  188. if not values.get("country_id"):
  189. if company.default_country_id:
  190. values["country_id"] = company.default_country_id.id
  191. else:
  192. values["country_id"] = "21"
  193. if not values.get("activities_country_id"):
  194. if company.default_country_id:
  195. values["activities_country_id"] = company.default_country_id.id
  196. else:
  197. values["activities_country_id"] = "21"
  198. if not values.get("lang"):
  199. if company.default_lang_id:
  200. values["lang"] = company.default_lang_id.code
  201. comp = request.env["res.company"]._company_default_get()
  202. values.update(
  203. {
  204. "display_data_policy": comp.display_data_policy_approval,
  205. "data_policy_required": comp.data_policy_approval_required,
  206. "data_policy_text": comp.data_policy_approval_text,
  207. "display_internal_rules": comp.display_internal_rules_approval,
  208. "internal_rules_required": comp.internal_rules_approval_required,
  209. "internal_rules_text": comp.internal_rules_approval_text,
  210. }
  211. )
  212. return values
  213. def get_products_share(self, is_company):
  214. product_obj = request.env["product.template"]
  215. products = product_obj.sudo().get_web_share_products(is_company)
  216. return products
  217. def get_countries(self):
  218. countries = request.env["res.country"].sudo().search([])
  219. return countries
  220. def get_langs(self):
  221. langs = request.env["res.lang"].sudo().search([])
  222. return langs
  223. def get_selected_share(self, kwargs):
  224. prod_obj = request.env["product.template"]
  225. product_id = kwargs.get("share_product_id")
  226. return prod_obj.sudo().browse(int(product_id)).product_variant_ids[0]
  227. def validation(self, kwargs, logged, values, post_file):
  228. user_obj = request.env["res.users"]
  229. sub_req_obj = request.env["subscription.request"]
  230. redirect = "easy_my_coop_website.becomecooperator"
  231. email = kwargs.get("email")
  232. is_company = kwargs.get("is_company") == "on"
  233. if is_company:
  234. is_company = True
  235. redirect = "easy_my_coop_website.becomecompanycooperator"
  236. email = kwargs.get("company_email")
  237. # TODO: Use a overloaded function with the captcha implementation
  238. if request.website.company_id.captcha_type == 'google':
  239. if (
  240. "g-recaptcha-response" not in kwargs
  241. or kwargs["g-recaptcha-response"] == ""
  242. ):
  243. values = self.fill_values(values, is_company, logged)
  244. values.update(kwargs)
  245. values["error_msg"] = _(
  246. "the captcha has not been validated,"
  247. " please fill in the captcha"
  248. )
  249. return request.render(redirect, values)
  250. elif not request.website.is_captcha_valid(
  251. kwargs["g-recaptcha-response"]
  252. ):
  253. values = self.fill_values(values, is_company, logged)
  254. values.update(kwargs)
  255. values["error_msg"] = _(
  256. "the captcha has not been validated,"
  257. " please fill in the captcha"
  258. )
  259. return request.render(redirect, values)
  260. # Check that required field from model subscription_request exists
  261. required_fields = sub_req_obj.sudo().get_required_field()
  262. error = {
  263. field for field in required_fields if not values.get(field)
  264. } # noqa
  265. if error:
  266. values = self.fill_values(values, is_company, logged)
  267. values["error_msg"] = _(
  268. "Some mandatory fields have not " "been filled"
  269. )
  270. values = dict(values, error=error, kwargs=kwargs.items())
  271. return request.render(redirect, values)
  272. if not logged and email:
  273. user = user_obj.sudo().search([("login", "=", email)])
  274. if user:
  275. values = self.fill_values(values, is_company, logged)
  276. values.update(kwargs)
  277. values["error_msg"] = _(
  278. "There is an existing account for this"
  279. " mail address. Please login before "
  280. "fill in the form"
  281. )
  282. return request.render(redirect, values)
  283. else:
  284. confirm_email = kwargs.get("confirm_email")
  285. if email != confirm_email:
  286. values = self.fill_values(values, is_company, logged)
  287. values.update(kwargs)
  288. values["error_msg"] = _(
  289. "The email and the confirmation "
  290. "email doesn't match.Please check "
  291. "the given mail addresses"
  292. )
  293. return request.render(redirect, values)
  294. company = request.website.company_id
  295. if company.allow_id_card_upload:
  296. if not post_file:
  297. values = self.fill_values(values, is_company, logged)
  298. values.update(kwargs)
  299. values["error_msg"] = _(
  300. "You need to upload a" " scan of your id card"
  301. )
  302. return request.render(redirect, values)
  303. iban = kwargs.get("iban")
  304. if iban.strip():
  305. valid = sub_req_obj.check_iban(iban)
  306. if not valid:
  307. values = self.fill_values(values, is_company, logged)
  308. values["error_msg"] = _("You iban account number is not valid")
  309. return request.render(redirect, values)
  310. # check the subscription's amount
  311. max_amount = company.subscription_maximum_amount
  312. if logged:
  313. partner = request.env.user.partner_id
  314. if partner.member:
  315. max_amount = max_amount - partner.total_value
  316. if company.unmix_share_type:
  317. share = self.get_selected_share(kwargs)
  318. if partner.cooperator_type != share.default_code:
  319. values = self.fill_values(values, is_company, logged)
  320. values["error_msg"] = _(
  321. "You can't subscribe two "
  322. "different types of share"
  323. )
  324. return request.render(redirect, values)
  325. total_amount = float(kwargs.get("total_parts"))
  326. if max_amount > 0 and total_amount > max_amount:
  327. values = self.fill_values(values, is_company, logged)
  328. values["error_msg"] = (
  329. _("You can't subscribe for an amount that " "exceed ")
  330. + str(max_amount)
  331. + company.currency_id.symbol
  332. )
  333. return request.render(redirect, values)
  334. return True
  335. @http.route(
  336. ["/subscription/get_share_product"],
  337. type="json",
  338. auth="public",
  339. methods=["POST"],
  340. website=True,
  341. )
  342. def get_share_product(self, share_product_id, **kw):
  343. product_template = request.env["product.template"]
  344. product = product_template.sudo().browse(int(share_product_id))
  345. return {
  346. product.id: {
  347. "list_price": product.list_price,
  348. "min_qty": product.minimum_quantity,
  349. "force_min_qty": product.force_min_qty,
  350. }
  351. }
  352. @http.route(
  353. ["/subscription/subscribe_share"],
  354. type="http",
  355. auth="public",
  356. website=True,
  357. )
  358. def share_subscription(self, **kwargs):
  359. sub_req_obj = request.env["subscription.request"]
  360. attach_obj = request.env["ir.attachment"]
  361. # List of file to add to ir_attachment once we have the ID
  362. post_file = []
  363. # Info to add after the message
  364. post_description = []
  365. values = {}
  366. for field_name, field_value in kwargs.items():
  367. if hasattr(field_value, "filename"):
  368. post_file.append(field_value)
  369. elif (
  370. field_name in sub_req_obj._fields
  371. and field_name not in _BLACKLIST
  372. ):
  373. values[field_name] = field_value
  374. elif (
  375. field_name in _EXTRA_FIELDS
  376. and field_name not in _BLACKLIST
  377. ):
  378. values[field_name] = field_value
  379. # allow to add some free fields or blacklisted field like ID
  380. elif field_name not in _TECHNICAL:
  381. post_description.append(
  382. "{}: {}".format(field_name, field_value)
  383. )
  384. logged = kwargs.get("logged") == "on"
  385. is_company = kwargs.get("is_company") == "on"
  386. response = self.validation(kwargs, logged, values, post_file)
  387. if response is not True:
  388. return response
  389. already_coop = False
  390. if logged:
  391. partner = request.env.user.partner_id
  392. values["partner_id"] = partner.id
  393. already_coop = partner.member
  394. elif kwargs.get("already_cooperator") == "on":
  395. already_coop = True
  396. values["already_cooperator"] = already_coop
  397. values["is_company"] = is_company
  398. if kwargs.get("data_policy_approved", "off") == "on":
  399. values["data_policy_approved"] = True
  400. if kwargs.get("internal_rules_approved", "off") == "on":
  401. values["internal_rules_approved"] = True
  402. lastname = kwargs.get("lastname").upper()
  403. firstname = kwargs.get("firstname").title()
  404. values["name"] = firstname + " " + lastname
  405. values["lastname"] = lastname
  406. values["firstname"] = firstname
  407. values["birthdate"] = datetime.strptime(
  408. kwargs.get("birthdate"), "%d/%m/%Y"
  409. ).date()
  410. values["source"] = "website"
  411. values["share_product_id"] = self.get_selected_share(kwargs).id
  412. values["address"] = kwargs.get("street_name") + ", " + kwargs.get("house_number")
  413. del values["street_name"]
  414. del values["house_number"]
  415. if is_company:
  416. if kwargs.get("company_register_number", is_company):
  417. values["company_register_number"] = re.sub(
  418. "[^0-9a-zA-Z]+", "", kwargs.get("company_register_number")
  419. )
  420. subscription_id = sub_req_obj.sudo().create_comp_sub_req(values)
  421. else:
  422. subscription_id = sub_req_obj.sudo().create(values)
  423. if subscription_id:
  424. for field_value in post_file:
  425. attachment_value = {
  426. "name": field_value.filename,
  427. "res_name": field_value.filename,
  428. "res_model": "subscription.request",
  429. "res_id": subscription_id,
  430. "datas": base64.encodestring(field_value.read()),
  431. "datas_fname": field_value.filename,
  432. }
  433. attach_obj.sudo().create(attachment_value)
  434. return self.get_subscription_response(values, kwargs)