This commit is contained in:
Benoît Vézina 2024-12-17 15:40:14 -05:00
parent fa4f1b2b19
commit 57c938bb8d
5 changed files with 81 additions and 7 deletions

View file

@ -2,10 +2,16 @@
{ {
'name': 'Customer Itch Cycle Management', 'name': 'Customer Itch Cycle Management',
'version': '1.0', 'version': '1.0',
'depends': ['base', 'sale'], 'depends': [
'author': 'Your Name', 'base',
'sale_stock'
],
'author': 'Benoit Vézina',
'category': 'Sales Management', 'category': 'Sales Management',
'summary': 'Manage customer itch cycles by product for proactive sales engagement.',
'website': 'https://www.bemade.org',
'description': "Manage customer itch cycles by product for proactive sales engagement.", 'description': "Manage customer itch cycles by product for proactive sales engagement.",
'license': 'AGPL-3',
'data': [ 'data': [
'views/itch_cycle_product_partner_view.xml', 'views/itch_cycle_product_partner_view.xml',
'views/res_partner_view.xml', 'views/res_partner_view.xml',

View file

@ -56,12 +56,58 @@ class ItchCycleProductPartner(models.Model):
store=True store=True
) )
manualy_set_cycle = fields.Integer(
string="Cycle moyen (jours) défini manuellement"
)
manualy_set_qty = fields.Float(
string="Quantité défini manuellement"
)
next_expected_date = fields.Date( next_expected_date = fields.Date(
string="Prochaine vente prévue", string="Prochaine vente prévue",
compute="_compute_next_expected_date", compute="_compute_next_expected_date",
store=True store=True
) )
manualy_set_next_date = fields.Date(
string="Prochaine vente prévue défini manuellement"
)
calc_next_date = fields.Date(
string="Prochaine vente prévue calculée",
compute="_compute_next_expected_date",
store=True
)
calc_average_cycle = fields.Integer(
string="Cycle moyen (jours) calculé",
compute="_compute_itch_cycle_duration",
store=True
)
calc_average_qty = fields.Float(
string="Quantité moyenne calculée",
compute="_compute_mean_quantity_ordered",
store=True
)
@api.depends('manualy_set_cycle','average_cycle')
def _compute_itch_cycle_duration(self):
for record in self:
if record.manualy_set_cycle:
record.calc_average_cycle = record.manualy_set_cycle
else:
record.calc_average_cycle = record.average_cycle
@api.depends('manualy_set_qty','max_quantity_ordered')
def _compute_mean_quantity_ordered(self):
for record in self:
if record.manualy_set_qty:
record.calc_average_qty = record.manualy_set_qty
else:
record.calc_average_qty = record.max_quantity
prediction_status = fields.Selection( prediction_status = fields.Selection(
selection=[ selection=[
('on_time', 'À lheure'), ('on_time', 'À lheure'),
@ -174,8 +220,8 @@ class ItchCycleProductPartner(models.Model):
sale_order_lines = self.env['sale.order.line'].search([ sale_order_lines = self.env['sale.order.line'].search([
('order_id.state', 'in', ['sale', 'done']), # Commandes confirmées ou terminées ('order_id.state', 'in', ['sale', 'done']), # Commandes confirmées ou terminées
('qty_delivered', '>', 0), # Quantité livrée supérieure à 0 ('qty_delivered', '>', 0), # Quantité livrée supérieure à 0
('product_id', '!=', False), # Exclure les lignes sans produit ('product_id', '!=', False) # Exclure les lignes sans produit
('order_id.partner_id', '=', 5024659), # un client pour test # ('order_id.partner_id', '=', 5024659), # un client pour test
]) ])
# Carte pour regrouper par couple (client, produit) # Carte pour regrouper par couple (client, produit)
@ -227,22 +273,27 @@ class ItchCycleProductPartner(models.Model):
}) })
return True return True
@api.depends('sale_order_line_ids')
def _compute_quantity_total_ordered(self): def _compute_quantity_total_ordered(self):
for record in self: for record in self:
record.quantity_total_ordered = sum(record.sale_order_line_ids.mapped('product_uom_qty')) record.quantity_total_ordered = sum(record.sale_order_line_ids.mapped('product_uom_qty'))
@api.depends('sale_order_line_ids')
def _compute_quantity_of_orders(self): def _compute_quantity_of_orders(self):
for record in self: for record in self:
record.quantity_of_orders = len(record.sale_order_line_ids) record.quantity_of_orders = len(record.sale_order_line_ids)
@api.depends('sale_order_line_ids')
def _compute_min_quantity_ordered(self): def _compute_min_quantity_ordered(self):
for record in self: for record in self:
record.min_quantity_ordered = min(record.sale_order_line_ids.mapped('product_uom_qty')) record.min_quantity_ordered = min(record.sale_order_line_ids.mapped('product_uom_qty'))
@api.depends('sale_order_line_ids')
def _compute_max_quantity_ordered(self): def _compute_max_quantity_ordered(self):
for record in self: for record in self:
record.max_quantity_ordered = max(record.sale_order_line_ids.mapped('product_uom_qty')) record.max_quantity_ordered = max(record.sale_order_line_ids.mapped('product_uom_qty'))
@api.depends('sale_order_line_ids')
def _compute_mean_quantity_ordered(self): def _compute_mean_quantity_ordered(self):
for record in self: for record in self:
record.mean_quantity_ordered = np.mean(record.sale_order_line_ids.mapped('product_uom_qty')) record.mean_quantity_ordered = np.mean(record.sale_order_line_ids.mapped('product_uom_qty'))

View file

@ -8,13 +8,13 @@ class ResPartner(models.Model):
itch_cycle_product_ids = fields.One2many( itch_cycle_product_ids = fields.One2many(
comodel_name='itch.cycle.product.partner', comodel_name='itch.cycle.product.partner',
inverse_name='partner_id', inverse_name='partner_id',
string="Itch Cycles Produits" string="Itch Cycles Products"
) )
reorder_cycle_product_ids = fields.One2many( reorder_cycle_product_ids = fields.One2many(
comodel_name='itch.cycle.product.partner', comodel_name='itch.cycle.product.partner',
inverse_name='partner_id', inverse_name='partner_id',
string="Itch Cycles Produits", string="Reorder Cycles Products",
domain=[('quantity_of_orders', '>', 1)] domain=[('quantity_of_orders', '>', 1)]
) )

View file

@ -8,6 +8,18 @@ class SaleOrderLine(models.Model):
string="Cycle Produit/Partenaire" string="Cycle Produit/Partenaire"
) )
stock_move_ids = fields.One2many(
comodel_name='stock.move',
inverse_name='sale_line_id',
string="Mouvements de stock"
)
sale_date = fields.Datetime(
string="Date de vente",
related='order_id.date_order',
store=True
)
@api.model_create_multi @api.model_create_multi
def create(self, vals_list): def create(self, vals_list):
# Appeler le super pour créer les lignes # Appeler le super pour créer les lignes

View file

@ -29,6 +29,11 @@
<group string="Informations principales"> <group string="Informations principales">
<field name="partner_id"/> <field name="partner_id"/>
<field name="product_id"/> <field name="product_id"/>
<group string="Surchage manuelle">
<field name="manualy_set_cycle"/>
<field name="manualy_set_qty"/>
<field name="manualy_set_next_date"/>
</group>
</group> </group>
<group string="Statistiques"> <group string="Statistiques">
<field name="itch_cycle_duration" readonly="1"/> <field name="itch_cycle_duration" readonly="1"/>
@ -36,7 +41,6 @@
<field name="last_purchase_date" readonly="1"/> <field name="last_purchase_date" readonly="1"/>
<field name="next_expected_date" readonly="1"/> <field name="next_expected_date" readonly="1"/>
<field name="next_follow_up_date"/> <field name="next_follow_up_date"/>
<field name="prediction_status" widget="statusbar" options="{'on_time': 'green', 'delayed': 'red'}"/>
<field name="quantity_of_orders" readonly="1"/> <field name="quantity_of_orders" readonly="1"/>
<field name="quantity_total_ordered" readonly="1"/> <field name="quantity_total_ordered" readonly="1"/>
<field name="min_quantity_ordered" readonly="1"/> <field name="min_quantity_ordered" readonly="1"/>
@ -52,6 +56,7 @@
<field name="product_id"/> <field name="product_id"/>
<field name="price_unit"/> <field name="price_unit"/>
<field name="product_uom_qty"/> <field name="product_uom_qty"/>
<field name="sale_date"/>
<field name="discount"/> <field name="discount"/>
</tree> </tree>
</field> </field>