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.

330 lines
10 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. # Copyright 2020 Coop IT Easy SCRL fs
  2. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
  3. import logging
  4. import uuid
  5. from odoo import api, fields, models
  6. from odoo.exceptions import UserError, ValidationError
  7. from odoo.tools.translate import _
  8. _logger = logging.getLogger(__name__)
  9. class BeesdooProduct(models.Model):
  10. _inherit = "product.template"
  11. eco_label = fields.Many2one(
  12. "beesdoo.product.label", domain=[("type", "=", "eco")]
  13. )
  14. local_label = fields.Many2one(
  15. "beesdoo.product.label", domain=[("type", "=", "local")]
  16. )
  17. fair_label = fields.Many2one(
  18. "beesdoo.product.label", domain=[("type", "=", "fair")]
  19. )
  20. origin_label = fields.Many2one(
  21. "beesdoo.product.label", domain=[("type", "=", "delivery")]
  22. )
  23. main_seller_id = fields.Many2one(
  24. "res.partner",
  25. string="Main Seller",
  26. compute="_compute_main_seller_id",
  27. store=True,
  28. )
  29. display_unit = fields.Many2one("uom.uom")
  30. default_reference_unit = fields.Many2one("uom.uom")
  31. display_weight = fields.Float(
  32. compute="_compute_display_weight", store=True
  33. )
  34. total_with_vat = fields.Float(
  35. compute="_compute_total",
  36. store=True,
  37. string="Total Sales Price with VAT",
  38. )
  39. total_with_vat_by_unit = fields.Float(
  40. compute="_compute_total",
  41. store=True,
  42. string="Total Sales Price with VAT by Reference Unit",
  43. )
  44. total_deposit = fields.Float(
  45. compute="_compute_total", store=True, string="Deposit Price"
  46. )
  47. label_to_be_printed = fields.Boolean("Print label?")
  48. label_last_printed = fields.Datetime("Label last printed on")
  49. note = fields.Text("Comments")
  50. # S0023 : List_price = Price HTVA, so add a suggested price
  51. list_price = fields.Float(string="exVAT Price")
  52. suggested_price = fields.Float(
  53. string="Suggested exVAT Price", compute="_compute_cost", readOnly=True
  54. )
  55. deadline_for_sale = fields.Integer(string="Deadline for sale(days)")
  56. deadline_for_consumption = fields.Integer(
  57. string="Deadline for consumption(days)"
  58. )
  59. ingredients = fields.Char(string="Ingredient")
  60. scale_label_info_1 = fields.Char(string="Scale lable info 1")
  61. scale_label_info_2 = fields.Char(string="Scale lable info 2")
  62. scale_sale_unit = fields.Char(
  63. compute="_compute_scale_sale_uom", string="Scale sale unit", store=True
  64. )
  65. scale_category = fields.Many2one(
  66. "beesdoo.scale.category", string="Scale Category"
  67. )
  68. scale_category_code = fields.Integer(
  69. related="scale_category.code",
  70. string="Scale category code",
  71. readonly=True,
  72. store=True,
  73. )
  74. @api.depends("uom_id", "uom_id.category_id", "uom_id.category_id.type")
  75. @api.multi
  76. def _compute_scale_sale_uom(self):
  77. for product in self:
  78. if product.uom_id.category_id.type == "unit":
  79. product.scale_sale_unit = "F"
  80. elif product.uom_id.category_id.type == "weight":
  81. product.scale_sale_unit = "P"
  82. def _get_main_supplier_info(self):
  83. suppliers = self.seller_ids.sorted(
  84. key=lambda seller: seller.date_start, reverse=True
  85. )
  86. if suppliers:
  87. return suppliers[0]
  88. else:
  89. return suppliers
  90. @api.multi
  91. def generate_barcode(self):
  92. self.ensure_one()
  93. if self.to_weight:
  94. seq_internal_code = self.env.ref(
  95. "beesdoo_product.seq_ean_product_internal_ref"
  96. )
  97. bc = ""
  98. if not self.default_code:
  99. rule = self.env["barcode.rule"].search(
  100. [
  101. (
  102. "name",
  103. "=",
  104. "Price Barcodes (Computed Weight) 2 Decimals",
  105. )
  106. ]
  107. )[0]
  108. default_code = seq_internal_code.next_by_id()
  109. while (
  110. self.search_count([("default_code", "=", default_code)])
  111. > 1
  112. ):
  113. default_code = seq_internal_code.next_by_id()
  114. self.default_code = default_code
  115. ean = "02" + self.default_code[0:5] + "000000"
  116. bc = ean[0:12] + str(
  117. self.env["barcode.nomenclature"].ean_checksum(ean)
  118. )
  119. else:
  120. rule = self.env["barcode.rule"].search(
  121. [("name", "=", "Beescoop Product Barcodes")]
  122. )[0]
  123. size = 13 - len(rule.pattern)
  124. ean = rule.pattern + str(uuid.uuid4().fields[-1])[:size]
  125. bc = ean[0:12] + str(
  126. self.env["barcode.nomenclature"].ean_checksum(ean)
  127. )
  128. # Make sure there is no other active member with the same barcode
  129. while self.search_count([("barcode", "=", bc)]) > 1:
  130. ean = rule.pattern + str(uuid.uuid4().fields[-1])[:size]
  131. bc = ean[0:12] + str(
  132. self.env["barcode.nomenclature"].ean_checksum(ean)
  133. )
  134. _logger.info("barcode :", bc)
  135. self.barcode = bc
  136. @api.multi
  137. @api.depends("seller_ids", "seller_ids.date_start")
  138. def _compute_main_seller_id(self):
  139. for product in self:
  140. # Calcule le vendeur associé qui a la date de début la plus récente
  141. # et plus petite qu’aujourd’hui
  142. sellers_ids = product._get_main_supplier_info()
  143. product.main_seller_id = (
  144. sellers_ids and sellers_ids[0].name or False
  145. )
  146. @api.multi
  147. @api.depends(
  148. "taxes_id",
  149. "list_price",
  150. "taxes_id.amount",
  151. "taxes_id.tax_group_id",
  152. "display_weight",
  153. "weight",
  154. )
  155. def _compute_total(self):
  156. for product in self:
  157. consignes_group = self.env.ref(
  158. "beesdoo_product.consignes_group_tax", raise_if_not_found=False
  159. )
  160. taxes_included = set(product.taxes_id.mapped("price_include"))
  161. if len(taxes_included) == 0:
  162. product.total_with_vat = product.list_price
  163. return True
  164. elif len(taxes_included) > 1:
  165. raise ValidationError(
  166. _("Several tax strategies (price_include) defined for %s")
  167. % product.name
  168. )
  169. elif taxes_included.pop():
  170. product.total_with_vat = product.list_price
  171. product.total_deposit = sum(
  172. [
  173. tax._compute_amount(
  174. product.list_price, product.list_price
  175. )
  176. for tax in product.taxes_id
  177. if tax.tax_group_id == consignes_group
  178. ]
  179. )
  180. else:
  181. tax_amount_sum = sum(
  182. [
  183. tax._compute_amount(
  184. product.list_price, product.list_price
  185. )
  186. for tax in product.taxes_id
  187. if tax.tax_group_id != consignes_group
  188. ]
  189. )
  190. product.total_with_vat = product.list_price + tax_amount_sum
  191. product.total_deposit = sum(
  192. [
  193. tax._compute_amount(product.list_price, product.list_price)
  194. for tax in product.taxes_id
  195. if tax.tax_group_id == consignes_group
  196. ]
  197. )
  198. if product.display_weight > 0:
  199. product.total_with_vat_by_unit = (
  200. product.total_with_vat / product.weight
  201. )
  202. @api.multi
  203. @api.depends("weight", "display_unit")
  204. def _compute_display_weight(self):
  205. for product in self:
  206. product.display_weight = (
  207. product.weight * product.display_unit.factor
  208. )
  209. @api.multi
  210. @api.constrains("display_unit", "default_reference_unit")
  211. def _unit_same_category(self):
  212. for product in self:
  213. if (
  214. product.display_unit.category_id
  215. != product.default_reference_unit.category_id
  216. ):
  217. raise UserError(
  218. _(
  219. "Reference Unit and Display Unit should belong to the "
  220. "same category "
  221. )
  222. )
  223. @api.multi
  224. @api.depends("seller_ids")
  225. def _compute_cost(self):
  226. for product in self:
  227. suppliers = product._get_main_supplier_info()
  228. if len(suppliers) > 0:
  229. product.suggested_price = (
  230. suppliers[0].price * product.uom_po_id.factor
  231. ) * (
  232. 1
  233. + suppliers[0].product_tmpl_id.categ_id.profit_margin / 100
  234. )
  235. class BeesdooScaleCategory(models.Model):
  236. _name = "beesdoo.scale.category"
  237. _description = "beesdoo.scale.category"
  238. name = fields.Char(string="Scale name category")
  239. code = fields.Integer(string="Category code")
  240. _sql_constraints = [
  241. (
  242. "code_scale_categ_uniq",
  243. "unique (code)",
  244. "The code of the scale category must be unique !",
  245. )
  246. ]
  247. class BeesdooProductLabel(models.Model):
  248. _name = "beesdoo.product.label"
  249. _description = "beesdoo.product.label"
  250. name = fields.Char()
  251. type = fields.Selection(
  252. [
  253. ("eco", "Écologique"),
  254. ("local", "Local"),
  255. ("fair", "Équitable"),
  256. ("delivery", "Distribution"),
  257. ]
  258. )
  259. color_code = fields.Char()
  260. active = fields.Boolean(default=True)
  261. class BeesdooProductCategory(models.Model):
  262. _inherit = "product.category"
  263. profit_margin = fields.Float(default="10.0", string="Product Margin [%]")
  264. @api.multi
  265. @api.constrains("profit_margin")
  266. def _check_margin(self):
  267. for product in self:
  268. if product.profit_margin < 0.0:
  269. raise UserError(_("Percentages for Profit Margin must > 0."))
  270. class BeesdooProductSupplierInfo(models.Model):
  271. _inherit = "product.supplierinfo"
  272. price = fields.Float("exVAT Price")
  273. class BeesdooUOMCateg(models.Model):
  274. _inherit = "uom.category"
  275. type = fields.Selection(
  276. [
  277. ("unit", "Unit"),
  278. ("weight", "Weight"),
  279. ("time", "Time"),
  280. ("distance", "Distance"),
  281. ("surface", "Surface"),
  282. ("volume", "Volume"),
  283. ("other", "Other"),
  284. ],
  285. string="Category type",
  286. default="unit",
  287. )