This question has been flagged
8 Replies
7051 Views

Hai,


Please help, so I need help with the formula for calculating parking rates from Datetime field references, such as the price increase every hour. examples of field activities such as car parking activities on the street in general.
and i have a model,

class ParkingLog(models.Model):
    _name='parking_management'
    _rec_name='vehicle_number'
    
    vehicle_number=fields.Many2one('vehicle_log',string='Nomor Kendaraan')
    vehicle_type=fields.Many2one('type_vehicle', string='Jenis Kendaraan', ondelete='cascade', related='vehicle_number.vehicle_tipe',)
    parking_start=fields.Datetime(string='Masuk', default=fields.Datetime.now, required='True', readonly='True')
    parking_end=fields.Datetime(string='Keluar',compute='' ,states={'in' : [('readonly', 'False')], 'paid' : [('readonly', 'False')]})
    billing_id=fields.Integer('Tarif', related='vehicle_type.billing_ids')
    staff_id=fields.Many2one('res.users',string='Petugas', default=lambda self: self.env.user, readonly='true')

and this is for the code on api that i tried to make,

@api.depends('parking_end')
    def tarif_parkir(self):
        if self.parking_end:
            tarif = datetime.strptime(self.tarif, '%m/%d/%Y')
            self.parking_end = (parking_start.today() - tarif).hours + 2000

example; for cars, the first 1 hour = 100 USD and the next hour increases by 200 USD / hour for motorbikes, the first hour = 50 USD and the next hour increases by 100 USD / hour

for almost a month I tried to explore, tried it myself, but no solution was found. and finally I tried asking it directly on the forum.

Beforehand, any answer I would appreciate. Thanks you 😃

Avatar
Discard
Yes sir but the count is
1 hours = 2000 for car and next hours will increase 2000
1 hours = 1500 for motorcycle and next hours will increase 1000

Pada tanggal 29 Okt 2018 5.47 PM, "Manish Bohra" <mkbohra1994@gmail.com> menulis:

Hey Your problem like

1 hour = 100 USD

2 hour = 150 USD

Right ..?

Sent by Odoo S.A. using Odoo.


Author

right sir that's my problem, but I have a different price calculation every hour. depending on the vehicle that will park. So what should I change is the API code and how is the code?

Best Answer

Hi, 
It seems to me that the equation for this case is : 

Billing = First_billing + ( Hours_passed - 1 )  * Amount

where : 

Hours_passed = number of hours passed for parking including the first hour.

First_billing = the first hour passed has a fixed price right ? a default price  that does not include any increased fees


If you agree then we'll see the code if you have any issue with it.


UPDATE: 

billing = fields.Monetary(string='Billing', store=True, readonly=True, compute='compute_tarif_parking', track_visibility='onchange')
@api.depends('parking_end')
def compute_tarif_parking(self):
   first_billing = 2000
for rec in self:
parking_end_days = abs(fields.Datetime.from_string(fields.Datetime.now()) - fields.Datetime.from_string(rec.parking_start)).days
parking_end_seconds = abs(fields.Datetime.from_string(fields.Datetime.now()) - fields.Datetime.from_string(rec.parking_start)).seconds
parking_end_hours = parking_end_days * 24 + parking_end_seconds // 3600
billing = first_billing + (parking_end_hours - 1) * 2000
rec.billing = billing
Avatar
Discard
Best Answer

Hey Your problem like

1 hour = 100 USD

2 hour = 150 USD

Right ..?

Hey I am Facing same problem but i am solve this using below UI and Method

So UI I am Suggest you.


Avatar
Discard

ok but ..

1 hour charges = 100 USD

if 1 hour and 10 min charges = 200 USD (100 USD Previous Hours + 100 USD for next hour )

right ?

Yes right sir, sorry i cant reply in odoo community couse need 8 karma for do it

Pada tanggal Sen, 29 Okt 2018 18.10, Manish Bohra <mkbohra1994@gmail.com> menulis:

ok but ..

1 hour charges = 100 USD

if 1 hour and 10 min charges = 200 USD (100 USD Previous Hours + 100 USD for next hour )

right ?

Sent by Odoo S.A. using Odoo.

Hey Answer UI Updated Check.

Author Best Answer

@Ibrahim yess i agree with u sir. i should do like this. but error log say

 billing = first_billing + (time1 - 1) * 2000

TypeError: unsupported operand type(s) for -: 'dict' and 'int'

@api.depends('parking_end')
    def tarif_parkir(self):
        first_billing = 2000
        time = ({'parking_end':fields.Datetime.now(self)})
        billing = first_billing + (time - 1) * 2000
        self.write=billing
Avatar
Discard

See my answer. I have updated it.

Author

no work sir. it doesn't work, actually I want to relate all of that with just one button state.

so when I click the 'paid' button in the state.

the "billing_id" field and the "parking_end" field appear immediately

thank you for your response sir

the code that I have updated to see the example you gave

class ParkingLog(models.Model):
    _name='parking_management'
    _rec_name='vehicle_number'
    
    
    vehicle_number=fields.Many2one('vehicle_log',string='Nomor Kendaraan')
    vehicle_type=fields.Many2one('type_vehicle', string='Jenis Kendaraan', ondelete='cascade', related='vehicle_number.vehicle_tipe',)
    parking_start=fields.Datetime(string='Masuk', default=fields.Datetime.now, required='True', readonly='True')

    parking_end=fields.Datetime(string='Keluar',compute='compute_tarif_parking' , store = True, track_visibility = 'onchange', states={'in' : [('readonly', 'False')], 'paid' : [('readonly', 'False')]})

    billing_id=fields.Integer('Tarif', related='vehicle_type.billing_ids')
    staff_id=fields.Many2one('res.users',string='Petugas', default=lambda self: self.env.user, readonly='true')
 
    state = fields.Selection([
                                ('in', 'In'),
                                ('out', 'Out'),
                                ('paid', 'Paid'),
                                ], string='Status', readonly='True', copy='False',
                                default='in')
    
    @api.multi
    def action_confirm(self):
        self.write({'state': 'in'})
    @api.multi
    def action_cancel(self):
        self.write({'state': 'out'})
    @api.multi
    def action_close(self):
        self.write({'parking_end':fields.Datetime.now(self)})
        self.write({'state':'paid'})
       
#     @api.multi('parking_end')
#     def tarif_parkir(self):
#         if self.parking_end:
#             tarif = datetime.strptime(self.tarif, '%m/%d/%Y')
#             self.parking_end = (parking_start.today() - tarif).hours + 2000

    @api.depends('parking_end')
    def compute_tarif_parking(self):
        first_billing = 2000
        for rec in self:
            parking_end_days = self(fields.Datetime.from_string(fields.Datetime.now()) - fields.Datetime.from_string(rec.parking_start)).days
            parking_end_seconds = self(fields.Datetime.from_string(fields.Datetime.now()) - fields.Datetime.from_string(rec.parking_start)).seconds
            parking_end_hours = parking_end_days * 24 + parking_end_seconds // 3600
            billing = first_billing + (parking_end_hours - 1) * 2000
            rec.billing = billing

on picture, when i click button "paid" the "out" field and the "tariff" field changes according to the hours and prices that apply
image.png



On Tue, Oct 30, 2018 at 3:21 PM Ibrahim <ibrahim.boudmir@gmail.com> wrote:

See my answer. I have updated it.

Sent by Odoo S.A. using Odoo.

Author

please help again. I have updated my questions 😃🙏

as you can see in my code, the compute attrs is set to Billing ( which is in your case the Tarif field ), not in parking_end as you did...

my code says : If parking_end changes, recompute the billing and sotre it in the database. which, i think, is accurate.

now since in your first comment you mentioned that when you click on button, you want to trigger the compute of the billing, you need to do this :

suppose that the name of your button is : get_tarif

@api.multi

def get_tarif(self):

parking_end_days = abs(fields.Datetime.from_string(fields.Datetime.now()) - fields.Datetime.from_string(self.parking_start)).days

parking_end_seconds = abs(fields.Datetime.from_string(fields.Datetime.now()) - fields.Datetime.from_string(self.parking_start)).seconds

parking_end_hours = parking_end_days * 24 + parking_end_seconds // 3600

billing = first_billing + (parking_end_hours - 1) * 2000

self.write({

'tarif' : billing})

I actually tried to reassemble the code sir, because about: abs
error log "undefined variabel abs"

On Tue, Oct 30, 2018 at 7:24 PM Ibrahim <ibrahim.boudmir@gmail.com> wrote:

as you can see in my code, the compute attrs is set to Billing ( which is in your case the Tarif field ), not in parking_end as you did...

my code says : If parking_end changes, recompute the billing and sotre it in the database. which, i think, is accurate.

now since in your first comment you mentioned that when you click on button, you want to trigger the compute of the billing, you need to do this :

suppose that the name of your button is : get_tarif

@api.multi

def get_tarif(self):

parking_end_days = abs(fields.Datetime.from_string(fields.Datetime.now()) - fields.Datetime.from_string(self.parking_start)).days

parking_end_seconds = abs(fields.Datetime.from_string(fields.Datetime.now()) - fields.Datetime.from_string(self.parking_start)).seconds

parking_end_hours = parking_end_days * 24 + parking_end_seconds // 3600

billing = first_billing + (parking_end_hours - 1) * 2000

self.write({

'tarif' : billing})

Sent by Odoo S.A. using Odoo.

nothing happen sir, i update code like.

billing_id=fields.Integer('Tarif', related='vehicle_type.billing_ids',states={'in' : [('readonly', 'False')], 'paid' : [('readonly', 'False')]}, store='True', readonly='True', compute='action_close', track_visibility='onchange')

then API,

@api.multi
    def action_close(self):
        first_billing = 2000

        parking_end_days = abs(fields.Datetime.from_string(fields.Datetime.now()) - fields.Datetime.from_string(self.parking_start)).days

        parking_end_seconds = abs(fields.Datetime.from_string(fields.Datetime.now()) - fields.Datetime.from_string(self.parking_start)).seconds

        parking_end_hours = parking_end_days * 24 + parking_end_seconds // 3600

        billing = first_billing + (parking_end_hours - 1) * 2000

        self.write({'paid' : billing}) 
        self.write({'parking_end':fields.Datetime.now(self)})
        self.write({'state':'paid'})   

is there something wrong sir?😀

On Wed, Oct 31, 2018 at 9:04 AM Fazryan Zyan <fazryanzyan@gmail.com> wrote:
I actually tried to reassemble the code sir, because about: abs
error log "undefined variabel abs"

On Tue, Oct 30, 2018 at 7:24 PM Ibrahim <ibrahim.boudmir@gmail.com> wrote:

as you can see in my code, the compute attrs is set to Billing ( which is in your case the Tarif field ), not in parking_end as you did...

my code says : If parking_end changes, recompute the billing and sotre it in the database. which, i think, is accurate.

now since in your first comment you mentioned that when you click on button, you want to trigger the compute of the billing, you need to do this :

suppose that the name of your button is : get_tarif

@api.multi

def get_tarif(self):

parking_end_days = abs(fields.Datetime.from_string(fields.Datetime.now()) - fields.Datetime.from_string(self.parking_start)).days

parking_end_seconds = abs(fields.Datetime.from_string(fields.Datetime.now()) - fields.Datetime.from_string(self.parking_start)).seconds

parking_end_hours = parking_end_days * 24 + parking_end_seconds // 3600

billing = first_billing + (parking_end_hours - 1) * 2000

self.write({

'tarif' : billing})

Sent by Odoo S.A. using Odoo.

Apart the error, you are not doing what i'm telling you. so unfortunately, i can't go further in this...

as i mentioned before, my code goes to the button's process. Stick to this and you will get what you're looking for.

To sum up, you want to calculate the tarif when you click on button. SO please, remove compute attribute from tarif field.

As for abs(), It is the mathematic absolute function. Ex abs(-45) = 45

I did it just for precision : that my number of days and seconds is positive.

Normally, it's a built-in function and does not need any import.

Author

thank you very much mr.Ibrahim , it turns out I was wrong in implementing the code.

my mistake is inside : self.write({'billing_id' : billing}) cause before is ({'paid' : billing})

the end result code is :

first_billing = 2000

parking_end_days = abs(fields.Datetime.from_string(fields.Datetime.now()) - fields.Datetime.from_string(self.parking_start)).days

parking_end_seconds = abs(fields.Datetime.from_string(fields.Datetime.now()) - fields.Datetime.from_string(self.parking_start)).seconds

parking_end_hours = parking_end_days * 24 + parking_end_seconds // 3600

billing = first_billing + (parking_end_hours - 1) * 2000

self.write({'billing_id' : billing})

Good news. good luck