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.

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