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.

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