@@ -6031,6 +6031,7 @@ def portal_quotes(self, **kw):
60316031 # Shredding bin pricing
60326032 shredding_prices = []
60336033 bin_sizes = [
6034+ ('box' , 'Shred Box (Standard Box)' ),
60346035 ('23' , '23 Gallon Shredinator' ),
60356036 ('32g' , '32 Gallon Bin' ),
60366037 ('32c' , '32 Gallon Console' ),
@@ -6039,7 +6040,7 @@ def portal_quotes(self, **kw):
60396040 ]
60406041
60416042 # Default base prices
6042- base_shred_prices = {'23' : 20.0 , '32g' : 35.0 , '32c' : 30.0 , '64' : 65.0 , '96' : 95.0 }
6043+ base_shred_prices = {'box' : 10.0 , ' 23' : 20.0 , '32g' : 35.0 , '32c' : 30.0 , '64' : 65.0 , '96' : 95.0 }
60436044
60446045 for bin_code , bin_name in bin_sizes :
60456046 # Check for negotiated rate
@@ -6180,6 +6181,7 @@ def generate_quote(self, **post):
61806181 if line_type == 'shredding' and bin_size :
61816182 # Get shredding bin product
61826183 xmlid_map = {
6184+ 'box' : 'records_management.product_shred_box' ,
61836185 '23' : 'records_management.product_shredding_bin_23' ,
61846186 '32g' : 'records_management.product_shredding_bin_32g' ,
61856187 '32c' : 'records_management.product_shredding_bin_32c' ,
@@ -6203,7 +6205,7 @@ def generate_quote(self, **post):
62036205 else :
62046206 price = base_shred_prices .get (bin_size , 35.0 )
62056207
6206- bin_names = {'23' : '23 Gallon' , '32g' : '32 Gallon Bin' , '32c' : '32 Gallon Console' , '64' : '64 Gallon' , '96' : '96 Gallon' }
6208+ bin_names = {'box' : 'Shred Box' , ' 23' : '23 Gallon' , '32g' : '32 Gallon Bin' , '32c' : '32 Gallon Console' , '64' : '64 Gallon' , '96' : '96 Gallon' }
62076209 description = '%s Shredding Service' % bin_names .get (bin_size , 'Shredding' )
62086210
62096211 elif line_type == 'pickup' :
@@ -6250,14 +6252,115 @@ def generate_quote(self, **post):
62506252
62516253 i += 1
62526254
6255+ # Log the quote creation
6256+ order .message_post (
6257+ body = _ ("Quote created via customer portal" ),
6258+ message_type = 'notification' ,
6259+ )
6260+
6261+ # Redirect to quote detail page where they can review, download PDF, or submit
6262+ return request .redirect ('/my/quotes/%s?new=1' % order .id )
6263+
6264+ @http .route (['/my/quotes/<int:order_id>' ], type = 'http' , auth = 'user' , website = True )
6265+ def portal_quote_detail (self , order_id , ** kw ):
6266+ """Display quote detail with options to download PDF or submit for service."""
6267+ values = self ._prepare_portal_layout_values ()
6268+ partner = request .env .user .partner_id .commercial_partner_id
6269+
6270+ # Get the quote
6271+ order = request .env ['sale.order' ].sudo ().search ([
6272+ ('id' , '=' , order_id ),
6273+ ('partner_id' , 'child_of' , partner .id ),
6274+ ], limit = 1 )
6275+
6276+ if not order :
6277+ return request .redirect ('/my/quotes?error=not_found' )
6278+
6279+ values .update ({
6280+ 'order' : order ,
6281+ 'is_new' : kw .get ('new' ) == '1' ,
6282+ 'submitted' : kw .get ('submitted' ) == '1' ,
6283+ 'partner' : partner ,
6284+ 'currency_symbol' : request .env .company .currency_id .symbol or '$' ,
6285+ })
6286+
6287+ return request .render ('records_management.portal_quote_detail' , values )
6288+
6289+ @http .route (['/my/quotes/<int:order_id>/pdf' ], type = 'http' , auth = 'user' , website = True )
6290+ def portal_quote_pdf (self , order_id , ** kw ):
6291+ """Download quote as PDF."""
6292+ partner = request .env .user .partner_id .commercial_partner_id
6293+
6294+ # Get the quote
6295+ order = request .env ['sale.order' ].sudo ().search ([
6296+ ('id' , '=' , order_id ),
6297+ ('partner_id' , 'child_of' , partner .id ),
6298+ ], limit = 1 )
6299+
6300+ if not order :
6301+ return request .redirect ('/my/quotes?error=not_found' )
6302+
62536303 # Generate PDF
62546304 report = request .env .ref ('sale.action_report_saleorder' )
62556305 pdf_content , _ = report ._render_qweb_pdf ([order .id ])
62566306 return request .make_response (pdf_content , headers = [
62576307 ('Content-Type' , 'application/pdf' ),
6258- ('Content-Disposition' , f 'attachment; filename="Quote_{ order . name } . pdf"' )
6308+ ('Content-Disposition' , 'attachment; filename="Quote_%s. pdf"' % order . name )
62596309 ])
62606310
6311+ @http .route (['/my/quotes/<int:order_id>/submit' ], type = 'http' , auth = 'user' , website = True , methods = ['POST' ], csrf = True )
6312+ def portal_quote_submit (self , order_id , ** post ):
6313+ """Submit quote for service - confirms the sale order."""
6314+ partner = request .env .user .partner_id .commercial_partner_id
6315+
6316+ # Get the quote
6317+ order = request .env ['sale.order' ].sudo ().search ([
6318+ ('id' , '=' , order_id ),
6319+ ('partner_id' , 'child_of' , partner .id ),
6320+ ('state' , '=' , 'draft' ),
6321+ ], limit = 1 )
6322+
6323+ if not order :
6324+ return request .redirect ('/my/quotes?error=not_found' )
6325+
6326+ # Add notes if provided
6327+ if post .get ('notes' ):
6328+ order .note = post ['notes' ]
6329+
6330+ # Add requested date if provided
6331+ if post .get ('requested_date' ):
6332+ order .commitment_date = post ['requested_date' ]
6333+
6334+ # Confirm the order
6335+ order .action_confirm ()
6336+
6337+ # Log the submission
6338+ order .message_post (
6339+ body = _ ("Quote submitted for service via customer portal" ),
6340+ message_type = 'notification' ,
6341+ )
6342+
6343+ # Create a portal request for tracking
6344+ portal_request_vals = {
6345+ 'name' : _ ('Service Request from Quote %s' ) % order .name ,
6346+ 'partner_id' : partner .id ,
6347+ 'request_type' : 'other' ,
6348+ 'state' : 'submitted' ,
6349+ 'created_via_portal' : True ,
6350+ 'description' : _ ('Services requested via portal quote generator. See Sale Order %s for details.' ) % order .name ,
6351+ }
6352+
6353+ # Link to department if available
6354+ if hasattr (partner , 'department_id' ) and partner .department_id :
6355+ portal_request_vals ['department_id' ] = partner .department_id .id
6356+
6357+ try :
6358+ request .env ['portal.request' ].sudo ().create (portal_request_vals )
6359+ except Exception :
6360+ pass # Don't fail if portal.request has issues
6361+
6362+ return request .redirect ('/my/quotes/%s?submitted=1' % order .id )
6363+
62616364 @http .route (['/my/inventory/temp' ], type = 'http' , auth = "user" , website = True )
62626365 def portal_inventory_temp (self , page = 1 , sortby = None , filterby = None , search = None , ** kw ):
62636366 """Temp inventory tab - backend-style list view"""
0 commit comments