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.

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