update_or_create with Django for sum old row - django

i'm trying to create a row in DATABASE and if exist update the old value to the new + old, with DJANGO. something like PHP above:
$sql= "IF EXISTS(SELECT * FROM April_sales WHERE label='".$product."') THEN
BEGIN
UPDATE francais SET sold=sold+'".$sold."' WHERE label='".$product."';
END;
ELSE
BEGIN
INSERT INTO April_sales (sold,sold) VALUES('".$sold."','".$product."');
END;
END IF;";
i'm receiving new row ,trying this:
query = April_sales.objects.get_or_create(product=product, sold= new_amount, date= timezone.now())
sum_value = query.sold + new_amount
query = April_sales(product=product, sold=sum_value , date=timezone.now())
query.save()

get_or_create of django always returns a tuple, you need two variables to catch what you want:
Try this:
query, created = April_sales.objects.get_or_create(product=product)
if created:
query.sold = new_amount
else:
query.sold += new_amount
query.date = timezone.now()
query.save()

I found the follow solution, it is not pretty and bit long:
if someone has a better suggestion, feel free to improve.
try:
query = April_sales.objects.get(product=product)
query.sold = query.sold + new_amount
query.date = timezone.now()
query.save()
except April_sales.DoesNotExist:
query = April_sales(product=product, sold=new_amount, date=timezone.now())
query.save()

Related

Django queryset for current year

I have my query written to get some thing from database and display on my website that query is getting all the data from db but what if i want to get the data particular to current year only
def get(self, request, *args, **kwargs):
filters = self.get_filters()
result = Model.objects.all().filter(*filters).distinct().aggregate(
t=Sum('t'),
b=Sum('b'),
)
result2 = Model.objects.all().filter(*filters).distinct().aggregate(
past_due=Sum('balance', filter=Q(due_date__lt=timezone.now()))
)
zero = Decimal('0.00')
total = result['t'] or zero
balance = result['b'] or zero
past_due = result2['past_due'] or zero
amount_received = t - b
I think filter=Q(due_date__year=datetime.now().date().year) should work for you, if I understand your question correctly.
This worked for me
result = Model.objects.all().filter(*filters, created__year=datetime.now().year).distinct().aggregate(
t=Sum('t'),
b=Sum('b'),
)
result2 = Model.objects.all().filter(*filters, created__year=datetime.now().year).distinct().aggregate(
past_due=Sum('balance', filter=Q(due_date__lt=timezone.now()))
)

Django querysets to subtract items

I have two query sets to get the values for stock_in and stock_out. How do i loop to subtract stock_out from stock_in
here are the querysets
stock_in = OrderItems.objects.values('drug').annotate(
quantity_received=Sum('quantity_received'),
).order_by('drug')
stock_out = RequestItems.objects.values('drug').annotate(
quantity_received=Sum('quantity_issued')
).order_by('drug')
Approach it from the Drug model. It makes it a bit easier on the query.
Drug.objects.annotate(
stock_in=Sum('orderitems_set__quantity_received'),
stock_out=Sum('requestitems_set__quantity_issued'),
).annotate(
current_stock=F('stock_in')-F('stock_out')
)
Or you might be able to do it in one. I'm not sure.
Drug.objects.annotate(
current_stock=Sum('orderitems_set__quantity_received') - Sum('requestitems_set__quantity_issued'),
)
def stock_list(request):
stock_in = OrderItems.objects.values('drug__drugTitle','drug__drugCode', 'drug__denom_quantity').order_by('drug').annotate(quant_in=Sum('quantity_received'))
stock_out = RequestItems.objects.values('drug__drugTitle', 'drug__drugCode', 'drug__denom_quantity').order_by('drug').annotate(quant_out=Sum('quantity_issued'))
stock_available=[]
index = 0
for item in stock_out:
if item is None:
remaining_stc = stock_in[index]['quant_in']
stock_available.append({'drug__drugTitle':stock_in[index]['drug__drugTitle'],'drug__drugCode':stock_in[index]['drug__drugCode'], 'drug__denom_quantity':stock_in[index]['drug__denom_quantity'], 'quantr':remaining_stc})
else:
remaining_stc = stock_in[index]['quant_in']-stock_out[index]['quant_out']
stock_available.append({'drug__drugTitle':stock_in[index]['drug__drugTitle'],'drug__drugCode':stock_in[index]['drug__drugCode'], 'drug__denom_quantity':stock_in[index]['drug__denom_quantity'], 'quantr':remaining_stc})
index = index + 1
context = {
"stock_available":stock_available,
}
return render(request, 'stock/stock_list.html', context)

django FilterSet for end of day

How to make the query take correct date from start date and end end of the day for FilterSet.
Now if you type start_filter_date = 2018.05.23 and end_filter_date = 2018.05.25. Then start_filter_date=2018.05.23T00:00 and end_filter_date=2018.05.25T00:00. Time is taken 00:00, but need to be 23:59?
My class is following:
class TaskFilterSet(django_filters.rest_framework.FilterSet):
id = django_filters.NumberFilter(name="pk")
start_filter_date = django_filters.DateFilter(name="date_added", lookup_expr="gte")
end_filter_date = django_filters.DateFilter(name="date_added", lookup_expr="lte")
i think the best way is use gte with lt but send end date date_added + timedelta(1), i don't use the django filters but based on the tips.html#solution-1-magic-values you can try:
class EndFilter(django_filters.DateFilter):
def filter(self, qs, value):
if value:
value = value + timdelta(1)
return super(EndFilter, self).filter(qs, value)
class TaskFilterSet(django_filters.rest_framework.FilterSet):
id = django_filters.NumberFilter(name="pk")
start_filter_date = django_filters.DateFilter(name="date_added", lookup_expr="gte")
end_filter_date = EndFilter(name="date_added", lookup_expr="lt")

Looking for a best way to insert a records from one model to another based on selection in odoo

I did the code for insert records from so_parts table to so_bo table using Query...How can I use ORM method to do this kind of job. Is there any other way(best)to do that? Here is my code`
`
#api.multi
def save_rapair_parts(self, vals):
#get todays date and convert it to string
created_date = datetime.datetime.today().strftime("%m/%d/%Y")
str_date = str(created_date)
so_p_id = self.so_p_id.id
bo_status = self.bo_status
so_part_t = self.so_part_t
so_part_sno = self.so_part_sno
product = self.so_part_product
product_str = 'Repair '+str(product)
part_id = self.id
bench_order_table.search(['id','bo_sno','created_date','bo_number','rep_description','bo_status'])
#insert details intoso bench orders
`
if so_part_t=='r_b':
try:
sequence = self.env['ir.sequence'].next_by_code('so.benchorder') or '/'
str_sequence = str(sequence)
query = """SELECT so_work_authorization FROM my_depots_so WHERE id=%d """ % (so_p_id)
self.env.cr.execute(query)
result = self.env.cr.fetchall()
result_number = json.dumps(result, ensure_ascii=False)
strip_number = result_number.strip('\' \" [] ')
work_auth_no = str(strip_number)
work_auth_no += "-"
work_auth_no += str_sequence
insert ="""INSERT INTO my_depots_so_bo(id,so_bo_id,bo_sno,created_date,bo_number,rep_description,bo_status) values %s """
parameters = (part_id,so_p_id,so_part_sno,str_date,work_auth_no,product_str,bo_status)
self.env.cr.execute(insert,(parameters,))
my_depots_bo(id,bo_sno,created_date,bo_number,rep_description,bo_status) values %s """
# self.env.cr.execute(insert_query, (parameters,))
except Exception:
print "Error in inserting values"`
yes there is a better way because when you use ORM
method you also checks access right for user to:
for your select query:
rec = self.env['my.depots.so'].search_read(['id', '=', so_p_id], ['so_work_authorization'])
if rec:
rec = rec[0] # search_read return a list of dictionary
so_work_authorization = rec['so_work_authorization']
# and do what ever you want with the result
# to create
# call create method witch accept a dictionary
# field_name : value
new_rec = self.env['my.depots.so.bo'].create({
'so_bo_id': so_p_id, # many2one must be an integer value
'bo_sno': bo_nso_value,
'bo_number': value_of_number,
# ....
# ....
# add al field
}) # create return the new created record as model object
for inserting use: self.env['model.name'].create(vals)
for updating use : self.env['model.name'].write(vals)
using ORM method makes sure that user don't pass the security access rigths
Hope you get the idea

How to include "None" in lte/gte comparisons?

I've got this complex filtering mechanism...
d = copy(request.GET)
d.setdefault('sort_by', 'created')
d.setdefault('sort_dir', 'desc')
form = FilterShipmentForm(d)
filter = {
'status': ShipmentStatuses.ACTIVE
}
exclude = {}
if not request.user.is_staff:
filter['user__is_staff'] = False
if request.user.is_authenticated():
exclude['user__blocked_by__blocked'] = request.user
if form.is_valid():
d = form.cleaned_data
if d.get('pickup_city'): filter['pickup_address__city__icontains'] = d['pickup_city']
if d.get('dropoff_city'): filter['dropoff_address__city__icontains'] = d['dropoff_city']
if d.get('pickup_province'): filter['pickup_address__province__exact'] = d['pickup_province']
if d.get('dropoff_province'): filter['dropoff_address__province__exact'] = d['dropoff_province']
if d.get('pickup_country'): filter['pickup_address__country__exact'] = d['pickup_country']
if d.get('dropoff_country'): filter['dropoff_address__country__exact'] = d['dropoff_country']
if d.get('min_price'): filter['target_price__gte'] = d['min_price']
if d.get('max_price'): filter['target_price__lte'] = d['max_price']
if d.get('min_distance'): filter['distance__gte'] = d['min_distance'] * 1000
if d.get('max_distance'): filter['distance__lte'] = d['max_distance'] * 1000
if d.get('available_on'): # <--- RELEVANT BIT HERE ---
filter['pickup_earliest__lte'] = d['available_on'] # basically I want "lte OR none"
filter['pickup_latest__gte'] = d['available_on']
if d.get('shipper'): filter['user__username__iexact'] = d['shipper']
order = ife(d['sort_dir'] == 'desc', '-') + d['sort_by']
shipments = Shipment.objects.filter(**filter).exclude(**exclude).order_by(order) \
.annotate(num_bids=Count('bids'), min_bid=Min('bids__amount'), max_bid=Max('bids__amount'))
And now my client tells me he wants pickup/drop-off dates to be 'flexible' as an option. So I've updated the DB to allow dates to be NULL for this purpose, but now the "available for pickup on" filter won't work as expected. It should include NULL/None dates. Is there an easy fix for this?
Flip the logic and use exclude(). What you really want to do is exclude any data that specifies a date that doesn't fit. If pickup_latest and pickup_earliest are NULL it shouldn't match the exclude query and wont be removed. Eg
exclude['pickup_latest__lt'] = d['available_on']
exclude['pickup_earliest__gt'] = d['available_on']
Most database engines don't like relational comparisons with NULL values. Use <field>__isnull to explicitly check if a value is NULL in the database, but you'll need to use Q objects to OR the conditions together.
Don't think that's actually a django-specific question. Variable 'd' is a python dictionary, no? If so, you can use this:
filter['pickup_latest__gte'] = d.get('available_on', None)