
    
i3M                     r    d dl m Z mZmZ ddlmZ ddlmZ  G d de      Z G d d	e      Z G d
 de      Z	y)    )datetimedate	timedelta   db   )	BaseModelc                      e Zd ZdZdZ ej                  ej                   ej                  d      d      Z	 ej                  ej                   ej                  d      d      Z
 ej                  ej                   ej                  d      d      Z ej                   ej                  d      d      Z ej                   ej                  d      d      Z ej                   ej                  d	      d      Z ej                   ej                  d
      d      Z ej                   ej                  d      d      Z ej                   ej                  d      d      Z ej                   ej                  d	      d      Z ej                   ej                  d
      d      Z ej                   ej                  d      d      Z ej                   ej                  d      d      Z ej                   ej.                  dd      d      Z ej                   ej                  d
      dd      Z ej                  ej4                  d      Z ej                  ej4                  d      Z ej                  ej:                  d      Z ej                  ej>                  dd      Z  ej                  ej>                  dd      Z! ej                  ej>                  dd      Z" ej                   ej                  d
      dd      Z# ej                   ej                  d      dd      Z$ ej                   ej                  d      dd      Z% ej                  ejL                        Z' ej                  ejL                        Z( ej                   ej                  d      dd      Z) ej                  ej>                  dd      Z* ej                  ej>                  dd      Z+ ej                  ejL                        Z, ej                  ejL                        Z- ej                  ej>                  dd      Z. ej                  ej>                  dd      Z/ ej                  ej>                  dd      Z0 ej                  ej>                  dd      Z1 ej                  ej                   ej                  d            Z2 ej                  ej>                  dd      Z3 ej                  ej>                  dd      Z4 ej                  ejL                        Z5 ej                   ej                  d      dd      Z6 ej                  ej:                        Z7 ej                  ej>                  dd      Z8 ej                   ej.                  dd      dd      Z9 ejt                  dd      Z; ejt                  de
gd      Z< ejt                  degd      Z= ejt                  dddd       Z> ejt                  d!ddd       Z?d" Z@d# ZAd$ ZBd% ZCd& ZDd' ZEd( ZFd) ZGd* ZHd+ ZId, ZJd- ZKd. ZLd/ ZMd0 ZNd1 ZOd2 ZPd3 ZQd4 ZRd5 ZSd6 ZTy7)8Contractz;Independent contractor agreements (Fair Work Act compliant)	contractszjobs.idFnullableusers.id   Tx         
   r   totaldefaultr   pending_agreement2   not_startedpending
completion      I@Job)backrefUsercontractor_contracts)foreign_keysr    worker_contractsPaymentcontractdynamicall, delete-orphanr    lazycascadeReviewc                     | j                   r| j                   S | j                  r/| j                  j                   d| j                  j                   S y)zKGet contractor name - uses snapshot if available, falls back to user object zUnknown Contractor)contractor_name
contractor
first_name	last_nameselfs    app/models/contract.pyget_contractor_namezContract.get_contractor_nameW   sH    '''??oo0014??3L3L2MNN#    c                     | j                   r| j                   S | j                  r/| j                  j                   d| j                  j                   S y)zGGet worker name - uses snapshot if available, falls back to user objectr.   zUnknown Worker)worker_nameworkerr1   r2   r3   s    r5   get_worker_namezContract.get_worker_name_   sH    ###;;kk,,-Qt{{/D/D.EFFr7   c                 x    | j                   r| j                   S | j                  r| j                  j                  S y)zLGet contractor email - uses snapshot if available, falls back to user objectN)contractor_emailr0   emailr3   s    r5   get_contractor_emailzContract.get_contractor_emailg   s1      (((????(((r7   c                 x    | j                   r| j                   S | j                  r| j                  j                  S y)zHGet worker email - uses snapshot if available, falls back to user objectN)worker_emailr:   r>   r3   s    r5   get_worker_emailzContract.get_worker_emailo   s1    $$$;;;;$$$r7   c                 x    | j                   r| j                   S | j                  r| j                  j                  S y)zLGet contractor phone - uses snapshot if available, falls back to user objectN)contractor_phoner0   phone_numberr3   s    r5   get_contractor_phonezContract.get_contractor_phonew   s1      (((????///r7   c                 x    | j                   r| j                   S | j                  r| j                  j                  S y)zHGet worker phone - uses snapshot if available, falls back to user objectN)worker_phoner:   rE   r3   s    r5   get_worker_phonezContract.get_worker_phone   s1    $$$;;;;+++r7   c                 x    | j                   r| j                   S | j                  r| j                  j                  S y)zJGet contractor ABN - uses snapshot if available, falls back to user objectN)contractor_abnr0   
abn_numberr3   s    r5   get_contractor_abnzContract.get_contractor_abn   s1    &&&????---r7   c                 x    | j                   r| j                   S | j                  r| j                  j                  S y)zFGet worker ABN - uses snapshot if available, falls back to user objectN)
worker_abnr:   rL   r3   s    r5   get_worker_abnzContract.get_worker_abn   s-    ????";;;;)))r7   c                 x    | j                   r| j                   S | j                  r| j                  j                  S y)zTGet contractor business name - uses snapshot if available, falls back to user objectN)contractor_business_namer0   business_namer3   s    r5   get_contractor_business_namez%Contract.get_contractor_business_name   s1    ((000????000r7   c                 x    | j                   r| j                   S | j                  r| j                  j                  S y)zPGet worker business name - uses snapshot if available, falls back to user objectN)worker_business_namer:   rS   r3   s    r5   get_worker_business_namez!Contract.get_worker_business_name   s1    $$,,,;;;;,,,r7   c                 6    | j                   xr | j                  S )z!Check if both parties have signed)contractor_signedworker_signedr3   s    r5   is_fully_signedzContract.is_fully_signed   s    %%<$*<*<<r7   c                     | j                   dk(  r| j                  sy| j                  syy| j                   dk(  ry| j                   dk(  ry| j                   d	k(  ry
| j                   S )z6Get what needs to happen next in the contract workflowr   contractor_reviewworker_reviewready_for_signingrY   waiting_worker_signaturerZ   waiting_contractor_signatureactivework_in_progress)statuscontractor_reviewedworker_reviewedr3   s    r5   get_next_stepzContract.get_next_step   sb    ;;--++*))&*[[//-[[O+1[[H$%{{r7   c                     | j                   dvry|| j                  k(  r| j                  sy|| j                  k(  r| j                  syy)z$Check if user can sign this contract)r   rY   rZ   FT)rd   contractor_idrY   	worker_idrZ   r4   user_ids     r5   can_signzContract.can_sign   sE    ;;YYd(((1G1G&t/A/Ar7   c                    | j                  |      sy|| j                  k(  r!d| _        t        j                         | _        n/|| j                  k(  r d| _        t        j                         | _        | j                  r| j                  rd| _	        d| _
        y| j                  r| j                  sd| _	        y| j                  r| j                  sd| _	        y)z#Sign the contract and update statusFTsignedr   rY   rZ   )rm   ri   rY   r   utcnowcontractor_signed_daterj   rZ   worker_signed_daterd   payment_statusrk   s     r5   sign_contractzContract.sign_contract   s    }}W% d(((%)D"*2//*;D'&!%D&.oo&7D# !!d&8&8"DK"+D  ##D,>,>-DK  (>(>)DKr7   c                 p    t        | j                        }| j                  j                  r
|dz  }||z   S |S )z:Calculate total contract value including GST if applicable皙?)floatagreed_rater:   gst_registered)r4   base_amount
gst_amounts      r5   calculate_total_valuezContract.calculate_total_value   s<    D,,- ;;%%$t+J++r7   c                 p    | j                   dkD  s&| j                  | j                  z
  j                  dkD  ryy)z,Determine contract type for legal compliancei N     independent_contractorcasual_contractor)rx   end_date
start_datedaysr3   s    r5   get_contract_typezContract.get_contract_type   s3     e#(G'M'MPR'R+"r7   c                 6    | j                   xr | j                  S )z2Check if both parties have completed their ratings)contractor_ratedworker_ratedr3   s    r5   is_mutual_rating_completez"Contract.is_mutual_rating_complete   s    $$:):)::r7   c                     || j                   k(  r| j                  rdS dS || j                  k(  r| j                  rdS dS y)z$Get rating status specific to a user	completedr   not_authorized)ri   r   rj   r   rk   s     r5   get_rating_status_for_userz#Contract.get_rating_status_for_user   sE    d((("&"7"7;FYF&"&"3"3;BBr7   c                 ~    g }| j                   s|j                  d       | j                  s|j                  d       |S )z&Get summary of who still needs to rater0   r:   )r   appendr   )r4   r   s     r5   get_pending_ratings_summaryz$Contract.get_pending_ratings_summary  s6    $$NN<(  NN8$r7   c                 B   ddl m} ddlm} d| _        d| _         |j
                         | _        | j                  rQ| j                  j                  xs ddz   | j                  _        |j                  j                  | j                         | j                  rQ| j                  j                  xs ddz   | j                  _        |j                  j                  | j                         |j                  j                  |        |j                  j                          y )Nr   r   r   )r   r   r	   )
extensionsr   r   rd   completion_statusrp   worker_completion_dater:   jobs_completedsessionaddr0   commit)r4   r   r   s      r5   mark_as_completedzContract.mark_as_completed  s    #%!!,&5hoo&7# ;;*.++*D*D*IQ)NDKK&JJNN4;;'??.2oo.L.L.QPQUV-VDOO*JJNN4??+ 	

t


r7   c                 <    d| j                    d| j                   dS )Nz
<Contract  - >)idrd   r3   s    r5   __repr__zContract.__repr__!  s    DGG9C}A66r7   N)U__name__
__module____qualname____doc____tablename__r   ColumnInteger
ForeignKeyjob_idri   rj   Stringr/   r9   r=   rD   rK   rR   rA   rH   rO   rV   Numericrx   	rate_typeDater   r   Textscope_of_workBooleanindependent_contractor_statussuperannuation_requiredworkers_comp_coveredrd   r   rs   DateTimecontractor_approval_dater   review_hours_statusrY   rZ   rq   rr   worker_agreed_resolvecontractor_agreed_resolvere   rf   last_modified_byr   r   mutual_rating_completed_datepayment_termspayment_schedulehiring_fee_paidhiring_fee_amountrelationshipjobr0   r:   paymentsreviewsr6   r;   r?   rB   rF   rI   rM   rP   rT   rW   r[   rg   rm   rt   r|   r   r   r   r   r   r    r7   r5   r   r      s   EM RYYrzz=2==#;eLFBIIbjj-"--
*CeTM		"**mbmmJ&?%PI  bii			#>O"))IBIIcNT:K !ryy3$? ryy2>RYYyryy}t<N(ryy3$G299YRYYs^d;L299YRYYr]T:L9299R=48J$299YRYYs^dC "))JBJJr1->K		)"))B-5II277U3Jryy51HBIIbgg6M %.BIIbjj$QV$W!'bii

EER$299RZZO RYYyryy}.AERF!		)"))B-QVWRYYyryy}i%PN(ryy5&RYYr{{3#"))IBIIbM9uU "		"**eeLBIIbjj%%HM&RYYr{{3"2;;/ &BIIbjj%%P )		"**ee T $"))BJJNbii

EEJO ryy]R]]:-FG !ryyUUK299RZZGL#,299R[[#9  BIIibiim\ERM ryy)  bii

EEJO!		*"**R"3UUS "//%
5C }oOefJR__V9+GYZFry*9VjkHbooh
ThiG$ ="
8	#; ,7r7   r   c                      e Zd ZdZdZ ej                  ej                   ej                  d      d      Z	 ej                   ej                  d      dd      Z ej                   ej                  d	      d
      Z ej                   ej                  d	            Z ej                   ej                  d            Z ej                   ej                  d	      d
      Z ej                   ej                  d            Z ej                   ej"                  dd      d      Z ej                   ej"                  dd      d      Z ej                   ej"                  dd      dd      Z ej                   ej"                  dd      d      Z ej                   ej"                  dd      dd      Z ej                   ej"                  dd      dd      Z ej                   ej                  d      dd      Z ej                  ej2                  ej6                  d      Z ej                  ej2                        Z ej                  ej2                        Z ej                  ej>                  dd      Z  ej                  ej                  dd      Z! ej                  ej2                        Z" ejF                  dddd      Z$d Z%d Z&d Z'd Z(y)r%   z0Escrow payment system for construction contractsr   zcontracts.idFr   r   Tuniquer      )r   r   r   r   r         r   r      Invoicepaymentr'   r(   r)   c                 X    d| _         d| _        d| _        d| _        d| _        d| _        y)z5Calculate payment amounts - flat $50 hiring fee modelr   g      @r   N)platform_feegross_amountr{   net_to_workerwithholding_tax_amountwithholding_tax_rater3   s    r5   calculate_amountszPayment.calculate_amountsO  s3     "!&'#$%!r7   c                     | j                   dk7  ry| j                  r"t        j                         | j                  k  ry| j                  S )z,Check if payment can be released from escrowheld_escrowF)rd   dispute_deadliner   rp   release_conditions_metr3   s    r5   can_be_releasedzPayment.can_be_releasedY  s?    ;;-'   X__%69N9N%N***r7   c                    ddl m} | j                  }|j                  }|j                  }t
        j                  j                  | j                        j                         }|r|S |j                  syt        | j                        t        | j                        z
  }|j                  rdnd}t        | j                  |j                  d|j                  j                   t!        j"                         t!        j"                         t%        d	      z   |t        | j                        t        | j                        ||j&                  xs d
|j(                  xs |j*                   d|j,                   |j&                  xs d
|j(                  xs |j*                   d|j,                   d      }|j/                          |j1                         \  }	}
|	st3        d|
        t4        j6                  j9                  |       |S )z7Automatically generate invoice when payment is releasedr   )r!   )
payment_idNrv   g        zConstruction services for r~   )r   00000000000r.   sent)r   ri   descriptioninvoice_datedue_dateamount_ex_gstr{   total_amountgst_ratesupplier_abnsupplier_name	buyer_abn
buyer_namerd   u'   ⚠️ Invoice GST compliance warning: )app.models.userr!   r&   r:   r0   r   query	filter_byr   firstry   rw   r   r{   r   titler   todayr   rL   rS   r1   r2   generate_invoice_numbervalidate_gst_complianceprintr   r   r   )r4   r!   r&   r:   r0   existing_invoicer   r   invoiceis_compliantcompliance_errorss              r5   auto_generate_invoicezPayment.auto_generate_invoiced  s   (==((
 #==22dgg2FLLN## $$ d//053II!004c ww$--4X\\5G5G4HIZZ\I2$66'T__-t001**;m ..[V5F5F4GqIYIYHZ2[ ++<}!//dj6K6K5LAjNbNbMc3d
$ 	'') +2*I*I*K'';<M;NOP


wr7   c                 <    d| j                    d| j                   dS )Nz	<Payment r   r   )payment_referencerd   r3   s    r5   r   zPayment.__repr__  s"    4112#dkk]!DDr7   N))r   r   r   r   r   r   r   r   r   contract_idr   r   stripe_payment_intent_idstripe_client_secretstripe_statusstripe_transfer_idstripe_transfer_statusr   r   r   r{   r   r   r   rd   r   r   rp   date_initiateddate_held_escrowdate_releasedr   r   dispute_period_daysr   r   invoicesr   r   r   r   r   r7   r5   r%   r%   %  s   :M "))BJJn(EPUVK!		)"))B-uM  )ryy3E$299YRYYs^4BIIibiim,M"9299S>$?&RYYyryy}5 299ZRZZA.?L299ZRZZA.?L:2::b!,a%HJBIIjbjjQ/%@M %299ZRZZ1%5q5Q&RYYzrzz"a'8!eT RYYyryy}i%HF RYYr{{HOOeTN ryy-BIIbkk*M&RYYrzz55Q $"))BJJEJ ryy- ry))UijH&	+1fEr7   r%   c                      e Zd ZdZdZ ej                  ej                   ej                  d      d      Z	 ej                  ej                   ej                  d      d      Z
 ej                   ej                  d      dd	      Z ej                  ej                  ej                  d
      Z ej                  ej                  d      Z ej                  ej$                  d      Z ej                   ej(                  dd      d      Z ej                   ej(                  dd      d      Z ej                   ej(                  dd      d      Z ej                   ej(                  dd      dd
      Z ej                   ej                  d      d      Z ej                   ej                  d      d      Z ej                   ej                  d      d      Z ej                   ej                  d      d      Z ej                   ej                  d      dd
      Zd Zd Zd Z y)r   z-GST-compliant invoices for Australian tax lawr   zpayments.idFr   r   r   Tr   r   r   r   r   r   rv   r   r   r   draftc                     ddl }t        j                         j                  }t	        |j                               dd j                         }d| d| | _        y)zGenerate unique invoice numberr   N   RR-)uuidr   r   yearstruuid4upperinvoice_number)r4   r  r  
short_uuids       r5   r   zInvoice.generate_invoice_number  sK    zz|  &r*002
 "4&*6r7   c                 z   g }| j                   rt        | j                         dk7  r|j                  d       | j                  rt        | j                        dk7  r|j                  d       t	        | j
                        t	        | j                        z  }t        t	        | j                        |z
        dkD  r|j                  d       t	        | j
                        t	        | j                        z   }t        t	        | j                        |z
        dkD  r|j                  d       t        |      dk(  |fS )z2Validate invoice meets Australian GST requirementsr   zValid supplier ABN requiredzValid buyer ABN requiredg{Gz?zGST amount calculation errorzTotal amount calculation errorr   )
r   lenr   r   rw   r   r   absr{   r   )r4   errorsexpected_gstexpected_totals       r5   r   zInvoice.validate_gst_compliance  s       C(9(9$:b$@MM78~~T^^!4!:MM45 T//053GGuT__%45<MM89t112U4??5KKuT&&'.89D@MM:;6{a''r7   c                 <    d| j                    d| j                   dS )Nz	<Invoice z - $r   )r
  r   r3   s    r5   r   zInvoice.__repr__  s%    4../tD4E4E3FaHHr7   N)!r   r   r   r   r   r   r   r   r   r   ri   r   r
  r   r   r   r   r   r   r   r   r   r{   r   r   r   r   r   r   rd   r   r   r   r   r7   r5   r   r     s   7M 2::}r}}]'CeTJBIIbjj-"--
*CeTMRYYyryy}TEJN 299RWWdjj5ILryy51H"))BGGe4K BIIjbjjQ/%@M:2::b!,u=J299ZRZZA.?LryyAq)4%HH 299YRYYr]U;LBIIibiinu=M		)"))B-%8I9299S>E:J RYYyryy}gFF7(,Ir7   r   N)
r   r   r   r   r   baser
   r   r%   r   r   r7   r5   <module>r     s?    . .  \7y \7~sEi sEl<Ii <Ir7   