rairo commited on
Commit
14b1751
·
verified ·
1 Parent(s): 710f02f

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +89 -42
main.py CHANGED
@@ -673,14 +673,14 @@ def propose_deal():
673
 
674
  @app.route('/api/deals/<deal_id>/respond', methods=['POST'])
675
  def respond_to_deal(deal_id):
676
- auth_header = request.headers.get('Authorization');
677
- uid = None
678
  try:
679
  uid = verify_token(auth_header)
680
  if not FIREBASE_INITIALIZED: return jsonify({'error': 'Server configuration error'}), 503
681
 
682
  data = request.get_json()
683
- response_action = data.get('action')
684
 
685
  if response_action not in ['accept', 'reject']:
686
  return jsonify({'error': 'Invalid action. Must be "accept" or "reject".'}), 400
@@ -690,58 +690,105 @@ def respond_to_deal(deal_id):
690
 
691
  if not deal_data or not isinstance(deal_data, dict):
692
  return jsonify({'error': 'Deal not found.'}), 404
693
-
694
- if deal_data.get('farmer_id') != uid:
695
- return jsonify({'error': 'Not authorized to respond to this deal.'}), 403
696
- if deal_data.get('status') != 'proposed':
697
- return jsonify({'error': f"Deal cannot be responded to from current status: '{deal_data.get('status')}'."}), 400
 
 
 
 
 
 
 
 
 
 
 
 
 
698
 
699
  update_time = datetime.now(timezone.utc).isoformat()
700
- buyer_id = deal_data.get('buyer_id')
701
- listing_id = deal_data.get('listing_id')
702
 
703
- listing_data_for_notif = {}
 
 
 
 
 
 
 
 
704
  if listing_id:
705
  listing_data_for_notif = db.reference(f'listings/{listing_id}', app=db_app).get() or {}
706
- crop_type_for_notif = listing_data_for_notif.get('crop_type', 'your listing')
707
-
708
 
709
  if response_action == 'accept':
710
- if listing_id and isinstance(listing_data_for_notif, dict):
711
- available_quantity = listing_data_for_notif.get('quantity', 0)
712
- proposed_quantity = deal_data.get('proposed_quantity', 0)
713
- if proposed_quantity > available_quantity:
714
- deal_ref.update({
715
- 'status': 'rejected_by_system_insufficient_qty',
716
- 'system_rejection_at': update_time,
717
- 'system_rejection_reason': f'Listing quantity ({available_quantity}) insufficient for deal quantity ({proposed_quantity}) at time of acceptance.'
718
- })
719
- _send_system_notification(buyer_id, f"Your deal proposal for '{crop_type_for_notif}' could not be accepted by the farmer due to insufficient stock.", "deal_status_update", f"/deals/{deal_id}")
720
- return jsonify({'success': False, 'error': 'Deal could not be accepted. Listing quantity is no longer sufficient.'}), 409
 
 
 
 
 
 
 
 
721
 
722
- new_status = 'accepted_by_farmer'
723
- deal_ref.update({'status': new_status, 'farmer_responded_at': update_time}) # Changed from farmer_accepted_at
724
- _send_system_notification(
725
- buyer_id,
726
- f"Your deal proposal for '{crop_type_for_notif}' has been ACCEPTED by the farmer. It is now pending admin approval.",
727
- "deal_status_update",
728
- f"/deals/{deal_id}"
729
- )
 
 
 
 
 
 
 
 
 
 
 
730
  admins_ref = db.reference('users', app=db_app).order_by_child('is_admin').equal_to(True).get()
731
  if admins_ref:
732
  for admin_id_loop, _ in admins_ref.items():
733
- _send_system_notification(admin_id_loop, f"Deal ID {deal_id} for '{crop_type_for_notif}' has been accepted by farmer and needs your approval.", "admin_deal_approval_needed", f"/admin/deals/pending")
734
- return jsonify({'success': True, 'message': 'Deal accepted by farmer, pending admin approval.'}), 200
 
735
 
736
  elif response_action == 'reject':
737
- deal_ref.update({'status': 'rejected_by_farmer', 'farmer_responded_at': update_time}) # Changed from farmer_rejected_at
738
- _send_system_notification(
739
- buyer_id,
740
- f"Your deal proposal for '{crop_type_for_notif}' has been REJECTED by the farmer.",
741
- "deal_status_update",
742
- f"/deals/{deal_id}"
743
- )
744
- return jsonify({'success': True, 'message': 'Deal rejected by farmer.'}), 200
 
 
 
 
 
 
 
 
 
745
 
746
  except Exception as e:
747
  return handle_route_errors(e, uid_context=uid)
 
673
 
674
  @app.route('/api/deals/<deal_id>/respond', methods=['POST'])
675
  def respond_to_deal(deal_id):
676
+ auth_header = request.headers.get('Authorization')
677
+ uid = None # UID of the currently logged-in user responding
678
  try:
679
  uid = verify_token(auth_header)
680
  if not FIREBASE_INITIALIZED: return jsonify({'error': 'Server configuration error'}), 503
681
 
682
  data = request.get_json()
683
+ response_action = data.get('action') # 'accept' or 'reject'
684
 
685
  if response_action not in ['accept', 'reject']:
686
  return jsonify({'error': 'Invalid action. Must be "accept" or "reject".'}), 400
 
690
 
691
  if not deal_data or not isinstance(deal_data, dict):
692
  return jsonify({'error': 'Deal not found.'}), 404
693
+
694
+ current_deal_status = deal_data.get('status')
695
+ proposer_id = deal_data.get('proposer_id')
696
+ farmer_id_in_deal = deal_data.get('farmer_id')
697
+ buyer_id_in_deal = deal_data.get('buyer_id')
698
+
699
+ # Authorization Check: Who is allowed to respond?
700
+ can_respond = False
701
+ if current_deal_status == 'proposed':
702
+ if proposer_id == buyer_id_in_deal and uid == farmer_id_in_deal: # Buyer proposed, Farmer responds
703
+ can_respond = True
704
+ elif proposer_id == farmer_id_in_deal and uid == buyer_id_in_deal: # Farmer proposed/countered, Buyer responds
705
+ can_respond = True
706
+ # Add other statuses if a different party needs to respond (e.g., after admin action)
707
+
708
+ if not can_respond:
709
+ logger.warning(f"UID {uid} unauthorized to respond to deal {deal_id}. Deal status: {current_deal_status}, Proposer: {proposer_id}, Farmer: {farmer_id_in_deal}, Buyer: {buyer_id_in_deal}")
710
+ return jsonify({'error': 'Not authorized to respond to this deal at its current state.'}), 403
711
 
712
  update_time = datetime.now(timezone.utc).isoformat()
 
 
713
 
714
+ # Determine the other party for notification
715
+ other_party_id = None
716
+ if uid == farmer_id_in_deal:
717
+ other_party_id = buyer_id_in_deal
718
+ elif uid == buyer_id_in_deal:
719
+ other_party_id = farmer_id_in_deal
720
+
721
+ listing_id = deal_data.get('listing_id')
722
+ listing_data_for_notif = {}
723
  if listing_id:
724
  listing_data_for_notif = db.reference(f'listings/{listing_id}', app=db_app).get() or {}
725
+ crop_type_for_notif = listing_data_for_notif.get('crop_type', 'your listing/demand')
 
726
 
727
  if response_action == 'accept':
728
+ # Quantity check (if applicable, e.g., if responding to a proposal against a produce listing)
729
+ if proposer_id == buyer_id_in_deal and uid == farmer_id_in_deal: # Farmer accepting buyer's proposal
730
+ if listing_id and isinstance(listing_data_for_notif, dict):
731
+ available_quantity = listing_data_for_notif.get('quantity', 0)
732
+ proposed_quantity = deal_data.get('proposed_quantity', 0)
733
+ if proposed_quantity > available_quantity:
734
+ deal_ref.update({
735
+ 'status': 'rejected_by_system_insufficient_qty',
736
+ 'system_rejection_at': update_time,
737
+ 'system_rejection_reason': f'Listing quantity ({available_quantity}) insufficient for deal quantity ({proposed_quantity}) at time of acceptance.'
738
+ })
739
+ if other_party_id:
740
+ _send_system_notification(other_party_id, f"Your deal proposal for '{crop_type_for_notif}' could not be accepted due to insufficient stock.", "deal_status_update", f"/deals/{deal_id}")
741
+ return jsonify({'success': False, 'error': 'Deal could not be accepted. Listing quantity is no longer sufficient.'}), 409
742
+
743
+ # If a buyer accepts a farmer's counter-offer, or farmer accepts buyer's initial proposal
744
+ # The deal moves to 'accepted_by_farmer' or 'accepted_by_buyer' then to admin.
745
+ # For simplicity, let's assume both lead to a state needing admin approval.
746
+ # We need a clear "who accepted" field.
747
 
748
+ accepted_by_field = ""
749
+ new_status = ""
750
+ if uid == farmer_id_in_deal:
751
+ accepted_by_field = "farmer_accepted_at"
752
+ new_status = "accepted_by_farmer" # Farmer accepts buyer's proposal
753
+ notification_message_to_other_party = f"Your deal proposal for '{crop_type_for_notif}' has been ACCEPTED by the farmer. It is now pending admin approval."
754
+ elif uid == buyer_id_in_deal:
755
+ accepted_by_field = "buyer_accepted_at"
756
+ new_status = "accepted_by_buyer" # Buyer accepts farmer's offer/counter
757
+ notification_message_to_other_party = f"Your offer/counter-offer for '{crop_type_for_notif}' has been ACCEPTED by the buyer. It is now pending admin approval."
758
+ else: # Should not happen due to auth check
759
+ return jsonify({'error': 'Internal error determining accepter role.'}), 500
760
+
761
+ deal_ref.update({'status': new_status, accepted_by_field: update_time, 'last_responder_id': uid})
762
+
763
+ if other_party_id:
764
+ _send_system_notification(other_party_id, notification_message_to_other_party, "deal_status_update", f"/deals/{deal_id}")
765
+
766
+ # Notify admins
767
  admins_ref = db.reference('users', app=db_app).order_by_child('is_admin').equal_to(True).get()
768
  if admins_ref:
769
  for admin_id_loop, _ in admins_ref.items():
770
+ _send_system_notification(admin_id_loop, f"Deal ID {deal_id} for '{crop_type_for_notif}' has been accepted by {uid[:6]}... and needs your approval.", "admin_deal_approval_needed", f"/admin/deals/pending") # Path for admin to see pending deals
771
+
772
+ return jsonify({'success': True, 'message': f'Deal accepted by {("farmer" if uid == farmer_id_in_deal else "buyer")}, pending admin approval.'}), 200
773
 
774
  elif response_action == 'reject':
775
+ rejected_by_field = ""
776
+ new_status = ""
777
+ if uid == farmer_id_in_deal:
778
+ rejected_by_field = "farmer_rejected_at" # Or just 'responded_at'
779
+ new_status = "rejected_by_farmer"
780
+ notification_message_to_other_party = f"Your deal proposal for '{crop_type_for_notif}' has been REJECTED by the farmer."
781
+ elif uid == buyer_id_in_deal:
782
+ rejected_by_field = "buyer_rejected_at"
783
+ new_status = "rejected_by_buyer"
784
+ notification_message_to_other_party = f"Your offer/counter-offer for '{crop_type_for_notif}' has been REJECTED by the buyer."
785
+ else: # Should not happen
786
+ return jsonify({'error': 'Internal error determining rejector role.'}), 500
787
+
788
+ deal_ref.update({'status': new_status, rejected_by_field: update_time, 'last_responder_id': uid})
789
+ if other_party_id:
790
+ _send_system_notification(other_party_id, notification_message_to_other_party, "deal_status_update", f"/deals/{deal_id}")
791
+ return jsonify({'success': True, 'message': f'Deal rejected by {("farmer" if uid == farmer_id_in_deal else "buyer")}.'}), 200
792
 
793
  except Exception as e:
794
  return handle_route_errors(e, uid_context=uid)