1892 lines
78 KiB
PHP
1892 lines
78 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Settlement
|
|
*
|
|
* settlement settles fund distribution. this can be CB, driver, or restaurant
|
|
*
|
|
*/
|
|
|
|
|
|
class Crunchbutton_Settlement extends Cana_Model {
|
|
|
|
const DEFAULT_NOTES = 'Crunchbutton Orders';
|
|
|
|
const TEST_SUMMARY_FAX = '_PHONE_';
|
|
const TEST_SUMMARY_EMAIL = 'daniel@_DOMAIN_';
|
|
|
|
// id_orders equals or lower than that will be ignored
|
|
const CONFIG_KEY_ID_ORDER_START = 'settlement-id_order-start';
|
|
|
|
public function __construct( $filters = [] ) {
|
|
$this->filters = $filters;
|
|
ini_set( 'memory_limit', '-1' );
|
|
}
|
|
|
|
public function startRestaurant(){
|
|
|
|
$this->restaurants = self::restaurants( $this->filters );
|
|
|
|
foreach ( $this->restaurants as $restaurant ) {
|
|
$restaurant->_payableOrders = $restaurant->payableOrders( $this->filters );
|
|
$orders = [];
|
|
foreach( $restaurant->_payableOrders as $order ){
|
|
$orders[] = $this->orderExtractVariables( $order );
|
|
}
|
|
$restaurant->payment_data = $this->restaurantsProcessOrders( $orders );
|
|
}
|
|
return $this->restaurants;
|
|
}
|
|
|
|
public function startDriver(){
|
|
$_orders = self::orders( $this->filters );
|
|
$orders = [];
|
|
foreach ( $_orders as $order ) {
|
|
$orders[] = $this->orderExtractVariables( $order );
|
|
}
|
|
return $this->driversProcess( $orders );
|
|
}
|
|
|
|
public function paidOrdersByDriverBeforeSettlement( $id_driver ){
|
|
|
|
$order = Order::o( $this->id_order_start() );
|
|
|
|
$query = 'SELECT o.* FROM `order` o
|
|
INNER JOIN restaurant r ON r.id_restaurant = o.id_restaurant
|
|
INNER JOIN order_action oa ON oa.id_order = o.id_order AND oa.type = ?
|
|
WHERE DATE_FORMAT(o.date,"%Y-%m-%d %H:%i") <= ?
|
|
AND oa.id_admin = ?
|
|
AND o.name NOT LIKE "%test%"
|
|
AND r.name NOT LIKE "%test%"
|
|
ORDER BY o.date ASC';
|
|
$_orders = Order::q( $query, [ Crunchbutton_Order_Action::DELIVERY_DELIVERED, $order->date()->format('Y-m-d H:i'), $id_driver]);
|
|
foreach ( $_orders as $order ) {
|
|
$orders[] = $this->orderExtractVariables( $order );
|
|
}
|
|
return $this->driversProcess( $orders, true );
|
|
}
|
|
|
|
// https://github.com/crunchbutton/crunchbutton/issues/3234
|
|
public function driverWeeksSummaryShifts( $id_driver ){
|
|
$query = 'SELECT cs.*, asa.id_admin_shift_assign FROM admin_shift_assign AS asa
|
|
INNER JOIN community_shift cs ON cs.id_community_shift = asa.id_community_shift
|
|
WHERE asa.id_admin = "' . $id_driver . '"';
|
|
|
|
if( $this->filters[ 'start' ] ){
|
|
$query .= 'AND DATE( cs.date_start ) >= \'' . ( new DateTime( $this->filters[ 'start' ] ) )->format( 'Y-m-d' ) . '\'';
|
|
$query .= 'AND DATE( cs.date_start ) <= \'' . ( new DateTime( $this->filters[ 'end' ] ) )->format( 'Y-m-d' ) . '\'';
|
|
}
|
|
|
|
$shifts = Crunchbutton_Community_Shift::q( $query );
|
|
$_shifts = [];
|
|
foreach( $shifts as $shift ){
|
|
$_shift[ 'week' ] = str_pad( $shift->dateStart()->format( 'W' ), 2, '0', STR_PAD_LEFT );
|
|
$_shift[ 'year' ] = $shift->dateStart()->format( 'Y' );
|
|
$_shift[ 'day' ] = $shift->dateStart()->format( 'Ymd' );
|
|
$_shift[ 'day' ] = $shift->dateStart()->format( 'Ymd' );
|
|
$_shift[ 'date_day' ] = $shift->dateStart()->format( 'M jS Y' );
|
|
$_shift[ 'date_start' ] = $shift->dateStart()->format( 'M jS Y g:i:s A' );
|
|
$_shift[ 'date_end' ] = $shift->dateEnd()->format( 'M jS Y g:i:s A' );
|
|
$_shift[ 'hours' ] = $shift->duration();
|
|
$_shift[ 'id_admin_shift_assign' ] = $shift->id_admin_shift_assign;
|
|
$_shift[ 'id_community_shift' ] = $shift->id_community_shift;
|
|
$_shift[ 'driver_paid' ] = $shift->duration();
|
|
if( $_shift[ 'driver_paid' ] ){
|
|
$schedule_info = Cockpit_Payment_Schedule_Shift::checkShiftWasPaidDriver( $_shift[ 'id_admin_shift_assign' ] );
|
|
if( $schedule_info ){
|
|
$payment_info = $schedule_info->payment()->get( 0 );
|
|
if( $payment_info ){
|
|
$date = $payment_info->date();
|
|
$_shift[ 'paid_info' ] = [ 'id_payment' => $payment_info->id_payment, 'date' => $date->format( 'M jS Y g:i:s A' ) ];
|
|
}
|
|
}
|
|
}
|
|
$_shifts[] = $_shift;
|
|
}
|
|
return $_shifts;
|
|
}
|
|
|
|
public function driverWeeksSummaryOrders( $id_driver ){
|
|
$query = 'SELECT DISTINCT(o.id_order) AS id, o.* FROM `order` o
|
|
INNER JOIN order_action oa ON oa.id_order = o.id_order
|
|
WHERE
|
|
DATE( o.date ) >= \'' . ( new DateTime( $this->filters[ 'start' ] ) )->format( 'Y-m-d' ) . '\'
|
|
AND DATE( o.date ) <= \'' . ( new DateTime( $this->filters[ 'end' ] ) )->format( 'Y-m-d' ) . '\'
|
|
AND ( oa.type = "' . Crunchbutton_Order_Action::DELIVERY_DELIVERED . '"
|
|
OR oa.type = "' . Crunchbutton_Order_Action::DELIVERY_PICKEDUP . '"
|
|
OR oa.type = "' . Crunchbutton_Order_Action::DELIVERY_ACCEPTED . '"
|
|
OR oa.type = "' . Crunchbutton_Order_Action::DELIVERY_TRANSFERED . '" )
|
|
AND oa.id_admin = "' . $id_driver . '"
|
|
AND o.name NOT LIKE "%test%"
|
|
ORDER BY o.date DESC ';
|
|
$_orders = [];
|
|
$orders = Order::q( $query );
|
|
foreach( $orders as $order ) {
|
|
if( $order->getDeliveryDriver() && $order->getDeliveryDriver()->id_admin == $id_driver ){
|
|
$_order = $this->orderExtractVariables( $order );
|
|
$_order[ 'week' ] = str_pad( $order->date()->format( 'W' ), 2, '0', STR_PAD_LEFT );
|
|
$_order[ 'year' ] = $order->date()->format( 'Y' );
|
|
$_order[ 'day' ] = $order->date()->format( 'Ymd' );
|
|
$_order[ 'date_day' ] = $order->date()->format( 'M jS Y' );
|
|
if( $_order[ 'driver_paid' ] ){
|
|
$payment_info = Crunchbutton_Order_Transaction::orderPaymentInfoDriver( $_order[ 'id_order' ] );
|
|
if( $payment_info ){
|
|
$_order[ 'payment_info' ] = [ 'id_payment' => $payment_info->id_payment, 'date' => $payment_info->date()->format( 'M jS Y g:i:s A' ) ];
|
|
}
|
|
}
|
|
if( $_order[ 'driver_reimbursed' ] ){
|
|
$payment_info = Crunchbutton_Order_Transaction::orderReimbursementInfoDriver( $_order[ 'id_order' ] );
|
|
if( $payment_info ){
|
|
$_order[ 'reimbursed_info' ] = [ 'id_payment' => $payment_info->id_payment, 'date' => $payment_info->date()->format( 'M jS Y g:i:s A' ) ];
|
|
}
|
|
}
|
|
$_orders[] = $_order;
|
|
}
|
|
}
|
|
return $this->driversProcess( $_orders, true );
|
|
}
|
|
|
|
// get orders we have to pay
|
|
public static function orders( $filters ){
|
|
|
|
// Settlement Not Including Orders After Midnight #4414
|
|
$start = new DateTime( $filters[ 'start' ] );
|
|
$end = new DateTime( $filters[ 'end' ] . ' 00:00:00', new DateTimeZone( c::config()->timezone ) );
|
|
$end->modify( '+ 28 hours' );
|
|
|
|
$query = 'SELECT o.* FROM `order` o
|
|
INNER JOIN restaurant r ON r.id_restaurant = o.id_restaurant
|
|
WHERE DATE(o.date) >= "' . $start->format('Y-m-d') . '"
|
|
AND DATE_FORMAT(o.date,"%Y-%m-%d %H:%i") <= "' . $end->format('Y-m-d H:i') . '"
|
|
AND o.name NOT LIKE "%test%"
|
|
AND r.name NOT LIKE "%test%"
|
|
ORDER BY o.date ASC';
|
|
return Order::q( $query );
|
|
}
|
|
|
|
// shifts we have to pay hourly
|
|
public function workedShiftsByPeriod( $id_admin, $filters ){
|
|
$start = ( new DateTime( $filters[ 'start' ] ) )->format( 'Y-m-d' );
|
|
$end = ( new DateTime( $filters[ 'end' ] ) )->format( 'Y-m-d' );
|
|
return Crunchbutton_Community_Shift::q( 'SELECT cs.*, asa.id_admin_shift_assign FROM community_shift cs
|
|
INNER JOIN admin_shift_assign asa ON asa.id_community_shift = cs.id_community_shift AND asa.id_admin = ' . $id_admin . '
|
|
WHERE
|
|
DATE_FORMAT( cs.date_start, "%Y-%m-%d" ) >= "' . $start . '"
|
|
AND
|
|
DATE_FORMAT( cs.date_start, "%Y-%m-%d" ) <= "' . $end . '"' );
|
|
}
|
|
|
|
|
|
// get restaurants that we need to pay
|
|
public static function restaurants($filters = []) {
|
|
$q = 'SELECT restaurant.*, MAX(p.date) AS last_pay, p.id_restaurant AS p_id_rest
|
|
FROM restaurant
|
|
LEFT OUTER JOIN ( SELECT id_restaurant, `date` FROM `payment` ) AS p using(id_restaurant)
|
|
INNER JOIN restaurant_payment_type rpt ON rpt.id_restaurant = restaurant.id_restaurant
|
|
WHERE 1=1 ';
|
|
if ($filters['payment_method']) {
|
|
$q .= ' AND rpt.payment_method = "'.$filters['payment_method']. '" ';
|
|
} else {
|
|
$q .= ' AND ( rpt.payment_method = "check" OR rpt.payment_method = "deposit" ) ';
|
|
}
|
|
$q .= ' AND rpt.payment_method != "' . Crunchbutton_Restaurant_Payment_Type::PAYMENT_METHOD_NO_PAYMENT . '" ';
|
|
if( $filters[ 'id_restaurant' ] ){
|
|
$q .= ' AND restaurant.id_restaurant = "' . $filters[ 'id_restaurant' ] . '"';
|
|
}
|
|
$q .= ' AND restaurant.id_restaurant AND restaurant.name NOT LIKE "%test%"
|
|
GROUP BY restaurant.id_restaurant
|
|
ORDER BY (CASE WHEN p_id_rest IS NULL THEN 1 ELSE 0 END) ASC, restaurant.name ASC';
|
|
return Restaurant::q( $q );
|
|
}
|
|
|
|
|
|
// this method receives the restaurant orders and run the math
|
|
public function restaurantsProcessOrders( $orders, $recalculatePaidOrders = false ){
|
|
// start all with 0
|
|
$restaurant = [];
|
|
$pay = [ 'card_subtotal' => 0, 'cash_reimburse' => 0, 'tax' => 0, 'delivery_fee' => 0, 'tip' => 0, 'customer_fee' => 0, 'markup' => 0, 'credit_charge' => 0, 'restaurant_fee' => 0, 'promo_gift_card' => 0, 'apology_gift_card' => 0, 'order_payment' => 0, 'cash_subtotal' => 0 ];
|
|
foreach ( $orders as $order ) {
|
|
if( $order ){
|
|
|
|
// Pay if Refunded
|
|
if( ( $order[ 'refunded' ] == 1 && $order[ 'pay_if_refunded' ] == 0 ) ){
|
|
continue;
|
|
}
|
|
if( $order[ 'do_not_pay_restaurant' ] == 1 ){
|
|
continue;
|
|
}
|
|
if( $order[ 'restaurant_paid' ] && !$recalculatePaidOrders ){
|
|
continue;
|
|
}
|
|
$restaurant['restaurant'] = $order[ 'restaurant' ];
|
|
$pay[ 'card_subtotal' ] += $this->orderCardSubtotalPayment( $order );
|
|
$pay[ 'tax' ] += $this->orderTaxPayment( $order );
|
|
$pay[ 'delivery_fee' ] += $this->orderDeliveryFeePayment( $order );
|
|
$pay[ 'tip' ] += $this->orderTipPayment( $order );
|
|
$pay[ 'customer_fee' ] += $this->orderCustomerFeePayment( $order );
|
|
$pay[ 'markup' ] += $this->orderMarkupPayment( $order );
|
|
$pay[ 'credit_charge' ] += $this->orderCreditChargePayment( $order );
|
|
$pay[ 'restaurant_fee' ] += $this->orderRestaurantFeePayment( $order );
|
|
$pay[ 'promo_gift_card' ] += $this->orderPromoGiftCardPayment( $order );
|
|
$pay[ 'apology_gift_card' ] += $this->orderApologyGiftCardPayment( $order );
|
|
$pay[ 'order_payment' ] += $this->orderRestaurantOrderPayment( $order );
|
|
$pay[ 'cash_subtotal' ] += $this->orderCashSubtotalPayment( $order );
|
|
$pay[ 'cash_reimburse' ] += $this->orderReimburseCashOrder( $order );
|
|
$pay[ 'formal_relationship' ] = $order[ 'formal_relationship' ];
|
|
}
|
|
}
|
|
foreach ( $pay as $key => $val ) {
|
|
$pay[ $key ] = round( $val, 2 );
|
|
}
|
|
// sum
|
|
$pay[ 'total_due' ] = round( $this->orderCalculateTotalDue( $pay ), 2 );
|
|
|
|
$this->log( 'restaurantsProcessOrders', array_merge( $restaurant, $pay ) );
|
|
return $pay;
|
|
}
|
|
|
|
// this method receives the restaurant orders and run the math
|
|
public function driversProcess( $orders, $recalculatePaidOrders = false, $include_invites = true, $process_shifts = true, $id_driver = 0 ){
|
|
|
|
$pay = [];
|
|
|
|
foreach ( $orders as $order ) {
|
|
|
|
if( $order && $order[ 'id_admin' ] ){
|
|
|
|
// Refunded Driver Orders Should Show Up! #3568 -- !(Refunded orders are not paid)
|
|
// if( $order[ 'refunded' ] == 1 ){
|
|
// continue;
|
|
// }
|
|
|
|
$driver = $order[ 'id_admin' ];
|
|
|
|
if( !$pay[ $driver ] ){
|
|
$pay[ $driver ] = [ 'subtotal' => 0, 'tax' => 0, 'delivery_fee' => 0, 'tip' => 0, 'customer_fee' => 0, 'markup' => 0, 'credit_charge' => 0, 'restaurant_fee' => 0, 'gift_card' => 0, 'total_spent' => 0, 'orders' => [], 'invites_total' => 0, 'invites_total_payment' => 0 ];
|
|
$pay[ $driver ][ 'id_admin' ] = $driver;
|
|
$pay[ $driver ][ 'name' ] = $order[ 'driver' ];
|
|
$pay_type = Admin::o( $driver )->payment_type();
|
|
$pay[ $driver ][ 'using_pex' ] = $pay_type->using_pex;
|
|
if( $pay_type->using_pex_date ){
|
|
$pay[ $driver ][ 'using_pex_date' ] = $pay_type->using_pex_date()->format( 'Ymd' );
|
|
}
|
|
if( $pay_type->id_admin_payment_type ){
|
|
$pay[ $driver ][ 'pay_type' ][ 'payment_type' ] = $pay_type->payment_type;
|
|
} else {
|
|
$pay[ $driver ][ 'pay_type' ][ 'payment_type' ] = Crunchbutton_Admin_Payment_Type::PAYMENT_TYPE_ORDERS;
|
|
}
|
|
}
|
|
|
|
$order[ 'pay_info' ] = [];
|
|
$order[ 'pay_info' ][ 'pay_by_order' ] = ( $pay[ $driver ][ 'pay_type' ][ 'payment_type' ] != Crunchbutton_Admin_Payment_Type::PAYMENT_TYPE_HOURS ? 1 : 0 );
|
|
$order[ 'pay_info' ][ 'subtotal' ] = $this->orderSubtotalDriveryPay( $order );
|
|
$order[ 'pay_info' ][ 'tax' ] = $this->orderTaxDriverPay( $order );
|
|
$order[ 'pay_info' ][ 'delivery_fee' ] = $this->orderDeliveryFeeDriverPay( $order );
|
|
$order[ 'pay_info' ][ 'tip' ] = $this->orderTipDriverPay( $order );
|
|
$order[ 'pay_info' ][ 'customer_fee' ] = $this->orderCustomerFeeDriverPay( $order );
|
|
$order[ 'pay_info' ][ 'markup' ] = $this->orderMarkupDriverPay( $order );
|
|
$order[ 'pay_info' ][ 'credit_charge' ] = $this->orderCreditChargeDriverPay( $order );
|
|
$order[ 'pay_info' ][ 'restaurant_fee' ] = $this->orderRestaurantFeeDriverPay( $order );
|
|
$order[ 'pay_info' ][ 'gift_card' ] = $this->orderGiftCardDriverPay( $order );
|
|
$order[ 'pay_info' ][ 'total_reimburse' ] = $this->orderReimburseDriver( $order );
|
|
$order[ 'pay_info' ][ 'standard_reimburse' ] = $this->orderReimburseDriver( $order );
|
|
$order[ 'pay_info' ][ 'total_payment' ] = $this->orderCalculateTotalDueDriver( $order[ 'pay_info' ] );
|
|
$order[ 'pay_info' ][ 'total_spent' ] = $this->orderCalculateTotalSpent( $order );
|
|
$order[ 'pay_info' ][ 'driver_reimbursed' ] = $order[ 'driver_reimbursed' ];
|
|
|
|
if(
|
|
( $order[ 'do_not_reimburse_driver' ] == 1 ) ||
|
|
( $order[ 'driver_reimbursed' ] && !$recalculatePaidOrders ) || // Do not reimburse reimbursed orders
|
|
( $pay[ $driver ][ 'using_pex' ] && !$pay[ $driver ][ 'using_pex_date' ] ) || // Do not reimburse drivers that are using pex card #3876
|
|
( $pay[ $driver ][ 'using_pex' ] && $pay[ $driver ][ 'using_pex_date' ] && intval( $pay[ $driver ][ 'using_pex_date' ] ) <= intval( $order[ 'formatted_date' ] ) )
|
|
){
|
|
$order[ 'pay_info' ][ 'total_reimburse' ] = 0;
|
|
}
|
|
|
|
if( $order[ 'driver_paid' ] && !$recalculatePaidOrders ){
|
|
$order[ 'pay_info' ][ 'total_payment' ] = 0;
|
|
}
|
|
|
|
if( $order[ 'do_not_pay_driver' ] == 1 ){
|
|
$order[ 'pay_info' ][ 'tip' ] = 0;
|
|
$order[ 'pay_info' ][ 'delivery_fee' ] = 0;
|
|
$order[ 'pay_info' ][ 'total_payment' ] = 0;
|
|
}
|
|
|
|
$pay[ $driver ][ 'orders' ][] = $order;
|
|
|
|
if( $order[ 'do_not_pay_driver' ] == 1 ){
|
|
continue;
|
|
}
|
|
|
|
$pay[ $driver ][ 'subtotal' ] += $order[ 'pay_info' ][ 'subtotal' ];
|
|
$pay[ $driver ][ 'tax' ] += $order[ 'pay_info' ][ 'tax' ];
|
|
$pay[ $driver ][ 'delivery_fee' ] += $order[ 'pay_info' ][ 'delivery_fee' ];
|
|
$pay[ $driver ][ 'tip' ] += $order[ 'pay_info' ][ 'tip' ];
|
|
$pay[ $driver ][ 'customer_fee' ] += $order[ 'pay_info' ][ 'customer_fee' ];
|
|
$pay[ $driver ][ 'markup' ] += $order[ 'pay_info' ][ 'markup' ];
|
|
$pay[ $driver ][ 'credit_charge' ] += $order[ 'pay_info' ][ 'credit_charge' ];
|
|
$pay[ $driver ][ 'restaurant_fee' ] += $order[ 'pay_info' ][ 'restaurant_fee' ];
|
|
$pay[ $driver ][ 'gift_card' ] += $order[ 'pay_info' ][ 'gift_card' ];
|
|
$pay[ $driver ][ 'standard_reimburse' ] += $order[ 'pay_info' ][ 'standard_reimburse' ];
|
|
$pay[ $driver ][ 'total_reimburse' ] += $order[ 'pay_info' ][ 'total_reimburse' ];
|
|
$pay[ $driver ][ 'total_payment' ] += $order[ 'pay_info' ][ 'total_payment' ];
|
|
$pay[ $driver ][ 'total_spent' ] += $order[ 'pay_info' ][ 'total_spent' ];
|
|
}
|
|
}
|
|
|
|
// Get all the shifts between the dates
|
|
if( $process_shifts ){
|
|
$shifts = $this->shifts( $id_driver );
|
|
if( $shifts ){
|
|
foreach( $shifts as $shift ){
|
|
$driver = $shift->id_admin;
|
|
if( !$pay[ $driver ] ){
|
|
$pay[ $driver ] = [ 'subtotal' => 0, 'tax' => 0, 'delivery_fee' => 0, 'tip' => 0, 'customer_fee' => 0, 'markup' => 0, 'credit_charge' => 0, 'restaurant_fee' => 0, 'gift_card' => 0, 'total_spent' => 0, 'orders' => [] ];
|
|
$pay[ $driver ][ 'id_admin' ] = $driver;
|
|
$pay[ $driver ][ 'name' ] = $shift->name;
|
|
$pay[ $driver ][ 'using_pex' ] = $shift->using_pex;
|
|
$pay[ $driver ][ 'pay_type' ][ 'payment_type' ] = Crunchbutton_Admin_Payment_Type::PAYMENT_TYPE_HOURS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach( $pay as $id_driver => $driver ){
|
|
$pay_type = Admin::o( $id_driver )->payment_type();
|
|
if( $pay_type->payment_type == Crunchbutton_Admin_Payment_Type::PAYMENT_TYPE_HOURS ){
|
|
$shifts = $this->workedShiftsByPeriod( $id_driver, $this->filters );
|
|
$worked_shifts = [];
|
|
$pay[ $id_driver ][ 'salary_type' ] = Crunchbutton_Admin_Payment_Type::PAYMENT_TYPE_HOURS;
|
|
$pay[ $id_driver ][ 'shifts' ] = [ 'worked_total' => 0, 'amount' => 0, 'hour_rate' => $pay_type->hour_rate ];
|
|
foreach( $shifts as $shift ){
|
|
if( !Cockpit_Payment_Schedule_Shift::checkShiftWasPaidDriver( $shift->id_admin_shift_assign ) || $recalculatePaidOrders ){
|
|
$_shift = [];
|
|
$_shift[ 'id_community_shift' ] = $shift->id_community_shift;
|
|
$_shift[ 'id_admin_shift_assign' ] = $shift->id_admin_shift_assign;
|
|
$_shift[ 'period' ] = $shift->startEndToStringCommunityTz();
|
|
$_shift[ 'hours' ] = $shift->duration();
|
|
$_shift[ 'amount' ] = round( $shift->duration() * $pay_type->hour_rate, 2 );
|
|
$pay[ $id_driver ][ 'shifts' ][ 'worked_total' ]++;
|
|
$pay[ $id_driver ][ 'shifts' ][ 'amount' ] += round( $_shift[ 'amount' ], 2 );
|
|
$worked_shifts[] = $_shift;
|
|
}
|
|
}
|
|
$tip = 0;
|
|
foreach( $pay[ $id_driver ][ 'orders' ] as $id_order => $order ){
|
|
if( !$order[ 'driver_paid' ] || $recalculatePaidOrders ){
|
|
$tip += $order[ 'pay_info' ][ 'tip' ];
|
|
}
|
|
}
|
|
|
|
$pay[ $id_driver ][ 'worked_hours' ] = $pay[ $id_driver ][ 'shifts' ][ 'amount' ];
|
|
$pay[ $id_driver ][ 'total_payment' ] = ( $pay[ $id_driver ][ 'shifts' ][ 'amount' ] + $tip + $pay[ $id_driver ][ 'markup' ] );
|
|
$pay[ $id_driver ][ 'shifts' ][ 'worked' ] = $worked_shifts;
|
|
} else {
|
|
$pay[ $id_driver ][ 'salary_type' ] = Crunchbutton_Admin_Payment_Type::PAYMENT_TYPE_ORDERS;
|
|
}
|
|
}
|
|
|
|
// Add the invites data
|
|
// https://github.com/crunchbutton/crunchbutton/issues/2561#issuecomment-49223406
|
|
if( $include_invites ){
|
|
$amount_per_invited_user = $this->amount_per_invited_user();
|
|
$invites = $this->driverInvites();
|
|
if( $invites ){
|
|
foreach( $invites as $id_admin => $invites ){
|
|
$admin_credit = 0;
|
|
foreach( $invites as $_invite ){
|
|
$admin_credit += $_invite[ 'admin_credit' ];
|
|
}
|
|
if( !$pay[ $id_admin ] ){
|
|
$admin = Crunchbutton_Admin::o( $id_admin );
|
|
$pay[ $id_admin ] = [ 'id_admin' => $id_admin, 'name' => $admin->name, 'invites_total_payment' => 0 ];
|
|
}
|
|
$pay[ $id_admin ][ 'invites' ] = $invites;
|
|
$pay[ $id_admin ][ 'invites_total' ] = count( $invites );
|
|
|
|
$pay[ $id_admin ][ 'invites_total_payment' ] = max( 0, $admin_credit );
|
|
$pay[ $id_admin ][ 'total_payment' ] += $pay[ $id_admin ][ 'invites_total_payment' ];
|
|
if( !$pay[ $id_admin ][ 'total_spent' ] ){
|
|
$pay[ $id_admin ][ 'total_spent' ] = 0;
|
|
}
|
|
|
|
if( !$pay[ $id_admin ][ 'pay_type' ] || $pay[ $id_admin ][ 'pay_type' ][ 'payment_type' ] ){
|
|
$pay_type = Admin::o( $id_admin )->payment_type();
|
|
$pay[ $id_admin ][ 'using_pex' ] = $pay_type->using_pex;
|
|
if( $pay_type->id_admin_payment_type ){
|
|
$pay[ $id_admin ][ 'pay_type' ][ 'payment_type' ] = $pay_type->payment_type;
|
|
} else {
|
|
$pay[ $id_admin ][ 'pay_type' ][ 'payment_type' ] = Crunchbutton_Admin_Payment_Type::PAYMENT_TYPE_ORDERS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
usort( $pay, function( $a, $b ) {
|
|
return $a[ 'name'] > $b[ 'name' ];
|
|
} );
|
|
return $pay;
|
|
}
|
|
|
|
public function orderCalculateTotalSpent( $arr ){
|
|
return ( $arr[ 'subtotal' ] + $arr[ 'tax' ] ) * $arr[ 'delivery_service' ] * ( $arr[ 'formal_relationship' ] ? 0 : 1 );
|
|
}
|
|
|
|
public function orderCalculateTotalDueDriver( $pay ){
|
|
$total_due = ( ( $pay[ 'subtotal' ] +
|
|
$pay[ 'tax' ] +
|
|
$pay[ 'delivery_fee' ] +
|
|
$pay[ 'customer_fee' ] +
|
|
$pay[ 'markup' ] +
|
|
$pay[ 'credit_charge' ] +
|
|
$pay[ 'restaurant_fee' ] +
|
|
$pay[ 'gift_card' ] -
|
|
$pay[ 'total_reimburse' ] ) * $pay[ 'pay_by_order' ] ) + $pay[ 'tip' ];
|
|
return $total_due;
|
|
}
|
|
|
|
public function orderCalculateTotalDue( $pay ){
|
|
$total_due = $pay[ 'card_subtotal' ] +
|
|
$pay[ 'tax' ] +
|
|
$pay[ 'delivery_fee' ] +
|
|
$pay[ 'tip' ] +
|
|
$pay[ 'customer_fee' ] +
|
|
$pay[ 'markup' ] +
|
|
$pay[ 'credit_charge' ] +
|
|
$pay[ 'restaurant_fee' ] +
|
|
$pay[ 'promo_gift_card' ] +
|
|
$pay[ 'apology_gift_card' ] +
|
|
$pay[ 'cash_reimburse' ];
|
|
return ( max( $total_due, 0 ) ) * $pay[ 'formal_relationship' ];
|
|
}
|
|
|
|
// This method calculates the "base" charge for credit orders using the formula
|
|
// that Balanced and Stripe use.
|
|
public function orderBaseCreditCharge( $arr ){
|
|
return ( 0.3 + 0.029 * $arr[ 'total_charged' ] ) * $arr[ 'credit' ];
|
|
}
|
|
|
|
// This method calculates the base fee charged to the restaurant.
|
|
// It applies the Restaurant Fee % to the subtotal.
|
|
// It also applies the Fee % to the Delivery Fee and Tax, unless excplicitly excepted,
|
|
// or unless the restaurant has 3rd-party delivery.
|
|
public function orderBaseRestaurantFee( $arr ){
|
|
return ( $arr[ 'restaurant_fee_percent' ] * ( $arr[ 'subtotal' ] + ( 1 - $arr[ 'delivery_service' ] ) * ( 1 - $arr[ 'just_fee_on_subtotal' ] ) * ( $arr[ 'tip' ] + $arr[ 'delivery_fee' ] ) ) ) / 100;
|
|
}
|
|
|
|
// For cash orders: reimburse just the cost of the food, so Subtotal + Tax
|
|
public function orderReimburseCashOrder( $arr ){
|
|
return ( $arr[ 'subtotal' ] + $arr[ 'tax' ] ) * $arr[ 'cash' ] * $arr[ 'reimburse_cash_order' ];
|
|
}
|
|
|
|
// For the subtotal, we pay this to the restaurant for credit orders.
|
|
public function orderCardSubtotalPayment( $arr ){
|
|
return $arr[ 'subtotal' ] * $arr[ 'credit' ];
|
|
}
|
|
|
|
// Tax is also paid to the restaurant for credit orders.
|
|
public function orderTaxPayment( $arr ){
|
|
return $arr[ 'tax' ] * $arr[ 'credit' ];
|
|
}
|
|
|
|
// Delivery fee is paid to the restaurant for credit orders,
|
|
// unless we do delivery ourselves.
|
|
public function orderDeliveryFeePayment( $arr ){
|
|
return $arr[ 'delivery_fee' ] * $arr[ 'credit' ] * ( 1 - $arr[ 'delivery_service' ] );
|
|
}
|
|
|
|
// Tip is paid to the restaurant for credit orders
|
|
// unless we do delivery ourselves.
|
|
public function orderTipPayment( $arr ){
|
|
return $arr[ 'tip' ] * $arr[ 'credit' ] * ( 1 - $arr[ 'delivery_service' ] );
|
|
}
|
|
|
|
// We charge the restaurant when they collected our markup from cash orders,
|
|
// except for 3rd-party delivery, when this must be collected from the driver.
|
|
public function orderCustomerFeePayment( $arr ){
|
|
return - ( $arr[ 'service_fee' ] * $arr[ 'cash' ] * ( 1 - $arr[ 'delivery_service' ] ) );
|
|
}
|
|
|
|
// We charge the restaurant when they collected our markup from cash orders,
|
|
// except for 3rd-party delivery, when this must be collected from the driver.
|
|
public function orderMarkupPayment( $arr ){
|
|
return - ( $arr[ 'delivery_service_markup_value' ] * $arr[ 'cash' ] * ( 1 - $arr[ 'delivery_service' ] ) );
|
|
}
|
|
|
|
// We charge the restaurant our Credit Charge from Balanced except
|
|
// when explicitly agreed otherwise.
|
|
public function orderCreditChargePayment( $arr ){
|
|
return - ( $this->orderBaseCreditCharge( $arr ) * $arr[ 'pay_credit_charge' ] );
|
|
}
|
|
|
|
// We charge the restaurant our contracted fee in all cases.
|
|
public function orderRestaurantFeePayment( $arr ){
|
|
return - ( $this->orderBaseRestaurantFee( $arr ) );
|
|
}
|
|
|
|
// We charge the restaurants for Promo gift cards up to their Promo maximum.
|
|
// This is set to 0 at the moment because we told them it would only be for new users,
|
|
// and lots of people are using gift cards again and again.
|
|
// When this is fixed, I'll get rid of the "*0" in the formula.
|
|
public function orderPromoGiftCardPayment( $arr ){
|
|
return - ( min( [ $arr[ 'gift_card_paid_by_promotional' ], $arr[ 'promotion_maximum' ] ] ) * $arr[ 'credit' ] ) * 0;
|
|
}
|
|
|
|
// We charge restaurants for apology credits up to their apology credit maximum.
|
|
public function orderApologyGiftCardPayment( $arr ){
|
|
return - ( min( [ $arr[ 'gift_card_paid_by_restaurant' ], $arr[ 'max_apology_credit' ] ] ) * $arr[ 'credit' ] );
|
|
}
|
|
|
|
// Drivers are paid the subtotal for credit orders when we have no formal
|
|
// relationship with the restaurant and they had to buy the food themselves.
|
|
public function orderSubtotalDriveryPay( $arr ){
|
|
return $arr[ 'subtotal' ] * $arr[ 'credit' ] * ( 1 - $arr[ 'formal_relationship' ] ) * ( 1 - $arr[ 'paid_with_cb_card' ] ) * $arr[ 'delivery_service' ];
|
|
}
|
|
|
|
// Drivers are paid the tax for credit orders when we have no formal
|
|
// relationship with the restaurant and they had to buy the food themselves.
|
|
public function orderTaxDriverPay( $arr ){
|
|
return $arr[ 'tax' ] * $arr[ 'credit' ] * ( 1 - $arr[ 'formal_relationship' ] ) * ( 1 - $arr[ 'paid_with_cb_card' ] ) * $arr[ 'delivery_service' ];
|
|
}
|
|
|
|
// Drivers are paid the whole delivery fee from credit orders.
|
|
public function orderDeliveryFeeDriverPay( $arr ){
|
|
return $arr[ 'delivery_fee' ] * $arr[ 'credit' ] * $arr[ 'delivery_service' ];
|
|
}
|
|
|
|
// Reimburse: To quote above, drivers are only reimbursed (that is, reimbursed for subtotal + tax)
|
|
// on orders where they front the money (i.e. on credit orders to non-formal-relationship stores)
|
|
// https://github.com/crunchbutton/crunchbutton/issues/3232#issuecomment-47254475
|
|
// https://github.com/crunchbutton/crunchbutton/issues/3232#issuecomment-47283481
|
|
public function orderReimburseDriver( $arr ){
|
|
return ( $arr[ 'subtotal' ] + $arr[ 'tax' ] ) * $arr[ 'credit' ] * $arr[ 'delivery_service' ] * ( 1 - $arr[ 'formal_relationship' ] );
|
|
}
|
|
|
|
// Drivers are paid the whole tip from credit orders.
|
|
public function orderTipDriverPay( $arr ){
|
|
return $arr[ 'tip' ] * $arr[ 'credit' ];
|
|
}
|
|
|
|
// Drivers must pay us back our markup they collected in cash.
|
|
public function orderCustomerFeeDriverPay( $arr ){
|
|
return - ( $arr[ 'service_fee' ] * $arr[ 'cash' ] );
|
|
}
|
|
|
|
// Drivers must pay us back our markup they collected in cash.
|
|
public function orderMarkupDriverPay( $arr ){
|
|
return - ( $arr[ 'delivery_service_markup_value' ] * $arr[ 'cash' ] );
|
|
}
|
|
|
|
// Drivers are not charged credit card fee, or gift card charge, for their orders.
|
|
// We eat this cost, or assume it is taken into account when setting our markup.
|
|
public function orderCreditChargeDriverPay( $arr ){
|
|
return 0;
|
|
}
|
|
|
|
// Drivers are not charged credit card fee, or gift card charge, for their orders.
|
|
// We eat this cost, or assume it is taken into account when setting our markup.
|
|
public function orderRestaurantFeeDriverPay( $arr ){
|
|
return 0;
|
|
}
|
|
|
|
// Drivers are not charged credit card fee, or gift card charge, for their orders.
|
|
// We eat this cost, or assume it is taken into account when setting our markup.
|
|
public function orderGiftCardDriverPay( $arr ){
|
|
return 0;
|
|
}
|
|
|
|
// Sum the amount we have to pay
|
|
public function orderRestaurantOrderPayment( $arr ){
|
|
return $this->orderCardSubtotalPayment( $arr ) +
|
|
$this->orderTaxPayment( $arr ) +
|
|
$this->orderDeliveryFeePayment( $arr ) +
|
|
$this->orderTipPayment( $arr ) +
|
|
$this->orderCustomerFeePayment( $arr ) +
|
|
$this->orderMarkupPayment( $arr );
|
|
}
|
|
|
|
public function orderCashSubtotalPayment( $arr ){
|
|
return ( $arr[ 'subtotal' ] +
|
|
$arr[ 'tax' ] +
|
|
( $arr[ 'tip' ] + $arr[ 'delivery_fee' ] ) *
|
|
( 1 - $arr[ 'delivery_service' ] ) ) * $arr[ 'cash' ];
|
|
}
|
|
|
|
public function orderTotalFee( $arr ){
|
|
return $arr[ 'customer_fee_percent' ] + $arr[ 'restaurant_fee_percent' ];
|
|
}
|
|
|
|
public function orderExtractVariables( $order ){
|
|
// Get all variables
|
|
$values = [];
|
|
$values[ 'subtotal' ] = $order->subtotal();
|
|
$values[ 'tax' ] = $order->tax();
|
|
$values[ 'tip' ] = $order->tip();
|
|
$values[ 'final_price_plus_delivery_markup' ] = $order->final_price_plus_delivery_markup;
|
|
$values[ 'delivery_fee' ] = $order->deliveryFee();
|
|
$values[ 'service_fee' ] = $order->serviceFee();
|
|
$values[ 'customer_fee' ] = $order->customer_fee();
|
|
$values[ 'customer_fee_percent' ] = $order->restaurant()->fee_customer;
|
|
$values[ 'restaurant_fee_percent' ] = $order->restaurant_fee_percent();
|
|
$values[ 'delivery_service_markup' ] = $order->delivery_service_markup;
|
|
$values[ 'delivery_service_markup_value' ] = $order->delivery_service_markup_value;
|
|
$values[ 'id_admin' ] = $order->getDeliveryDriver()->id_admin; // driver
|
|
$values[ 'id_order' ] = $order->id_order; // driver
|
|
|
|
$values[ 'gift_card_total' ] = $order->chargedByCredit();
|
|
$values[ 'gift_card_paid_by_crunchbutton' ] = Crunchbutton_Credit::creditByOrderPaidBy( $order->id_order, Crunchbutton_Credit::PAID_BY_CRUNCHBUTTON );
|
|
$values[ 'gift_card_paid_by_restaurant' ] = Crunchbutton_Credit::creditByOrderPaidBy( $order->id_order, Crunchbutton_Credit::PAID_BY_RESTAURANT );
|
|
$values[ 'gift_card_paid_by_promotional' ] = Crunchbutton_Credit::creditByOrderPaidBy( $order->id_order, Crunchbutton_Credit::PAID_BY_PROMOTIONAL );
|
|
$values[ 'gift_card_paid_by_other_restaurant' ] = Crunchbutton_Credit::creditByOrderPaidBy( $order->id_order, Crunchbutton_Credit::PAID_BY_OTHER_RESTAURANT );
|
|
|
|
$values[ 'total_charged' ] = $order->charged();
|
|
$values[ 'promotion_maximum' ] = $order->restaurant()->payment_type()->max_pay_promotion;
|
|
$values[ 'max_apology_credit' ] = $order->restaurant()->payment_type()->max_apology_credit;
|
|
|
|
$values[ 'credit' ] = ( $order->pay_type == Crunchbutton_Order::PAY_TYPE_CREDIT_CARD ) ? 1 : 0;
|
|
$values[ 'cash' ] = ( $order->pay_type == Crunchbutton_Order::PAY_TYPE_CASH ) ? 1 : 0;
|
|
$values[ 'charge_credit_fee' ] = ( $order->restaurant()->charge_credit_fee > 0 ) ? 1 : 0;
|
|
$values[ 'pay_credit_charge' ] = ( $order->restaurant()->charge_credit_fee > 0 ) ? 1 : 0;
|
|
$values[ 'pay_promotion' ] = ( $order->restaurant()->payment_type()->max_pay_promotion > 0 ) ? 1 : 0;
|
|
$values[ 'just_fee_on_subtotal' ] = ( $order->restaurant()->fee_on_subtotal > 0 ) ? 1: 0;
|
|
$values[ 'delivery_service' ] = ( $order->delivery_service > 0 ) ? 1: 0;
|
|
$values[ 'formal_relationship' ] = ( $order->restaurant()->formal_relationship > 0 ) ? 1: 0;
|
|
$values[ 'paid_with_cb_card' ] = ( $order->paid_with_cb_card > 0 ) ? 1: 0;
|
|
$values[ 'refunded' ] = ( $order->refunded > 0 ) ? 1: 0;
|
|
$values[ 'do_not_pay_restaurant' ] = ( $order->do_not_pay_restaurant > 0 ) ? 1: 0;
|
|
$values[ 'do_not_pay_driver' ] = ( $order->do_not_pay_driver > 0 ) ? 1: 0;
|
|
$values[ 'do_not_reimburse_driver' ] = ( $order->do_not_reimburse_driver > 0 ) ? 1: 0;
|
|
$values[ 'pay_if_refunded' ] = ( $order->pay_if_refunded > 0 ) ? 1: 0;
|
|
$values[ 'reimburse_cash_order' ] = ( $order->reimburse_cash_order > 0 ) ? 1: 0;
|
|
|
|
// convert all to float -> mysql returns some values as string
|
|
foreach( $values as $key => $val ){
|
|
$values[ $key ] = floatval( $val );
|
|
}
|
|
|
|
$values[ 'restaurant_paid' ] = Cockpit_Payment_Schedule_Order::checkOrderWasPaidRestaurant( $order->id_order );
|
|
if( !$values[ 'restaurant_paid' ] ){
|
|
$values[ 'restaurant_paid' ] = Crunchbutton_Order_Transaction::checkOrderWasPaidRestaurant( $order->id_order );
|
|
}
|
|
|
|
$values[ 'driver_reimbursed' ] = Cockpit_Payment_Schedule_Order::checkOrderWasReimbursedDriver( $order->id_order );
|
|
if( !$values[ 'driver_reimbursed' ] ){
|
|
$values[ 'driver_reimbursed' ] = Crunchbutton_Order_Transaction::checkOrderWasReimbursedDriver( $order->id_order );
|
|
}
|
|
|
|
$values[ 'driver_paid' ] = Cockpit_Payment_Schedule_Order::checkOrderWasPaidDriver( $order->id_order );
|
|
if( !$values[ 'driver_paid' ] ){
|
|
$values[ 'driver_paid' ] = Crunchbutton_Order_Transaction::checkOrderWasPaidDriver( $order->id_order );
|
|
}
|
|
|
|
// Assumes the order was already paid
|
|
// Checklist for AFTER new settlement is deployed #3603 - item 2
|
|
$id_order_start = $this->id_order_start();
|
|
if( intval( $values[ 'id_order' ] ) <= $id_order_start ){
|
|
$values[ 'restaurant_paid' ] = true;
|
|
$values[ 'driver_reimbursed' ] = true;
|
|
$values[ 'driver_paid' ] = true;
|
|
}
|
|
|
|
if( $values[ 'id_admin' ] ){
|
|
$admin = Cockpit_Admin::o( intval( $values[ 'id_admin' ] ) );
|
|
$values[ 'driver' ] = $admin->name;
|
|
} else {
|
|
$values[ 'driver' ] = '';
|
|
}
|
|
|
|
$values[ 'name' ] = $order->name;
|
|
$values[ 'pay_type' ] = $order->pay_type;
|
|
$values[ 'restaurant' ] = $order->restaurant()->name;
|
|
$values[ 'date' ] = $order->date()->format( 'M jS Y g:i:s A' );
|
|
$values[ 'formatted_date' ] = $order->date()->format( 'Ymd' );
|
|
$values[ 'short_date' ] = $order->date()->format( 'M jS Y' );
|
|
|
|
return $values;
|
|
}
|
|
|
|
public function scheduleRestaurantPayment( $id_restaurants ){
|
|
$this->log( 'scheduleRestaurantPayment', $id_restaurants );
|
|
$restaurants = $this->startRestaurant();
|
|
foreach ( $restaurants as $_restaurant ) {
|
|
if( !$id_restaurants[ $_restaurant->id_restaurant ] ){
|
|
continue;
|
|
}
|
|
$notes = $id_restaurants[ $_restaurant->id_restaurant ][ 'notes' ];
|
|
$adjustment = $id_restaurants[ $_restaurant->id_restaurant ][ 'adjustment' ];
|
|
$id_restaurant = $_restaurant->id_restaurant;
|
|
$payment_data = $_restaurant->payment_data;
|
|
// the total dues should include the adjustment
|
|
$payment_data[ 'total_due' ] = $payment_data[ 'total_due' ] + $adjustment;
|
|
|
|
// check if it has any order to be paid
|
|
$shouldSchedule = ( $payment_data[ 'total_due' ] > 0 ) ? true : false;
|
|
|
|
foreach ( $_restaurant->_payableOrders as $order ) {
|
|
$alreadyPaid = Cockpit_Payment_Schedule_Order::checkOrderWasPaidRestaurant( $order->id_order );
|
|
if( !$alreadyPaid ){
|
|
$alreadyPaid = Crunchbutton_Order_Transaction::checkOrderWasPaidRestaurant( $order->id_order );
|
|
}
|
|
if( !$alreadyPaid ){
|
|
$shouldSchedule = true;
|
|
}
|
|
}
|
|
if( $shouldSchedule ){
|
|
// schedule it
|
|
$schedule = new Cockpit_Payment_Schedule;
|
|
$schedule->id_restaurant = $_restaurant->id_restaurant;
|
|
$schedule->date = date( 'Y-m-d H:i:s' );
|
|
$schedule->amount = max( $payment_data[ 'total_due' ], 0 );
|
|
$schedule->adjustment = $adjustment;
|
|
$schedule->pay_type = Cockpit_Payment_Schedule::PAY_TYPE_PAYMENT;
|
|
$schedule->type = Cockpit_Payment_Schedule::TYPE_RESTAURANT;
|
|
$schedule->status = Cockpit_Payment_Schedule::STATUS_SCHEDULED;
|
|
$schedule->note = $notes;
|
|
$schedule->id_admin = c::user()->id_admin;
|
|
$schedule->save();
|
|
$id_payment_schedule = $schedule->id_payment_schedule;
|
|
// save the orders
|
|
foreach ( $_restaurant->_payableOrders as $order ) {
|
|
$total_due = $this->restaurantsProcessOrders( [ $this->orderExtractVariables( $order ) ] );
|
|
$schedule_order = new Cockpit_Payment_Schedule_Order;
|
|
$schedule_order->id_payment_schedule = $id_payment_schedule;
|
|
$schedule_order->id_order = $order->id_order;
|
|
$schedule_order->amount = max( $total_due[ 'total_due' ], 0 );
|
|
$schedule_order->save();
|
|
}
|
|
$this->log( 'scheduleRestaurantPayment', $schedule->properties() );
|
|
}
|
|
}
|
|
$settlement = new Crunchbutton_Settlement( $this->filters );
|
|
Cana::timeout(function() use( $settlement ) {
|
|
$settlement->doRestaurantPayments();
|
|
} );
|
|
}
|
|
|
|
public function scheduleDriverArbitraryPayment( $id_driver, $amount, $pay_type, $notes ){
|
|
|
|
$this->log( 'scheduleDriverArbitraryPayment: start', [ $id_driver, $amount, $type, $notes ] );
|
|
|
|
$schedule = new Cockpit_Payment_Schedule;
|
|
$schedule->id_driver = $id_driver;
|
|
$schedule->date = date( 'Y-m-d H:i:s' );
|
|
$schedule->pay_type = $pay_type;
|
|
$schedule->amount = max( $amount, 0 );
|
|
$schedule->adjustment = 0;
|
|
$schedule->arbritary = 1;
|
|
$schedule->note = $notes;
|
|
$schedule->id_admin = c::user()->id_admin;
|
|
$schedule->type = Cockpit_Payment_Schedule::TYPE_DRIVER;
|
|
$schedule->status = Cockpit_Payment_Schedule::STATUS_SCHEDULED;
|
|
$schedule->save();
|
|
|
|
$id_payment_schedule = $schedule->id_payment_schedule;
|
|
|
|
$this->log( 'scheduleDriverArbitraryPayment: end', $schedule->properties() );
|
|
|
|
$this->payDriver( $id_payment_schedule );
|
|
|
|
return $id_payment_schedule;
|
|
|
|
}
|
|
|
|
public function sendDriverArbitraryPayment( $id_payment_schedule ){
|
|
if( $this->doDriverPayments( $id_payment_schedule ) ){
|
|
return $id_payment_schedule;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public function scheduleDriverPaymentTimeout( $_driver, $notes, $adjustment, $adjustment_notes, $id_driver, $type, $id_admin ){
|
|
|
|
if( !$type ){
|
|
return false;
|
|
}
|
|
|
|
$this->log( 'scheduleDriverPayment', [ 'id_driver' => $id_driver ] );
|
|
|
|
$shouldSchedule = false;
|
|
|
|
if( $type == Cockpit_Payment_Schedule::PAY_TYPE_REIMBURSEMENT ){
|
|
$shouldSchedule = ( $_driver[ 'total_reimburse' ] != 0 ) ? true : false;
|
|
} else {
|
|
$shouldSchedule = ( $_driver[ 'total_payment' ] != 0 ) ? true : false;
|
|
}
|
|
|
|
if( $_driver[ 'orders' ] ){
|
|
foreach ( $_driver[ 'orders' ] as $order ) {
|
|
if( $type == Cockpit_Payment_Schedule::PAY_TYPE_REIMBURSEMENT ){
|
|
if( !$order[ 'driver_reimbursed' ] ){
|
|
$shouldSchedule = true;
|
|
}
|
|
} else {
|
|
if( !$order[ 'driver_paid' ] ){
|
|
$shouldSchedule = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$invites = $_driver[ 'invites' ];
|
|
if( $type == Cockpit_Payment_Schedule::PAY_TYPE_REIMBURSEMENT ){
|
|
if( count( $invites ) > 0 ){
|
|
$shouldSchedule = true;
|
|
}
|
|
}
|
|
|
|
if( $shouldSchedule ){
|
|
|
|
// schedule it
|
|
$schedule = new Cockpit_Payment_Schedule;
|
|
$schedule->id_driver = $id_driver;
|
|
$schedule->date = date( 'Y-m-d H:i:s' );
|
|
|
|
if( $type == Cockpit_Payment_Schedule::PAY_TYPE_REIMBURSEMENT ){
|
|
$amount = $_driver[ 'total_reimburse' ] + $adjustment;
|
|
} else {
|
|
$amount = $_driver[ 'total_payment' ] + $adjustment;
|
|
$pay_type = Admin::o( $id_driver )->payment_type();
|
|
if( $pay_type->id_admin_payment_type && $pay_type->payment_type == Crunchbutton_Admin_Payment_Type::PAYMENT_TYPE_HOURS ){
|
|
$schedule->driver_payment_hours = 1;
|
|
} else {
|
|
$schedule->driver_payment_hours = 0;
|
|
}
|
|
}
|
|
|
|
// Range
|
|
$range = ( new DateTime( $this->filters[ 'start' ] ) )->format( 'm/d/Y' );
|
|
$range .= ' => ';
|
|
$range .= ( new DateTime( $this->filters[ 'end' ] ) )->format( 'm/d/Y' );
|
|
|
|
$schedule->amount = max( $amount, 0 );
|
|
$schedule->adjustment = $adjustment;
|
|
$schedule->range_date = $range;
|
|
$schedule->pay_type = $type;
|
|
$schedule->type = Cockpit_Payment_Schedule::TYPE_DRIVER;
|
|
$schedule->status = Cockpit_Payment_Schedule::STATUS_SCHEDULED;
|
|
$schedule->log = 'Schedule created';
|
|
$schedule->note = $notes;
|
|
$schedule->adjustment_note = $adjustment_notes;
|
|
$schedule->id_admin = $id_admin;
|
|
$schedule->save();
|
|
$id_payment_schedule = $schedule->id_payment_schedule;
|
|
|
|
if( $type == Cockpit_Payment_Schedule::PAY_TYPE_PAYMENT ){
|
|
if( $_driver[ 'shifts' ] && $_driver[ 'shifts' ][ 'worked' ] ){
|
|
foreach ( $_driver[ 'shifts' ][ 'worked' ] as $shift ) {
|
|
$schedule_shift = new Cockpit_Payment_Schedule_Shift;
|
|
$schedule_shift->id_payment_schedule = $id_payment_schedule;
|
|
$schedule_shift->id_admin_shift_assign = $shift[ 'id_admin_shift_assign' ];
|
|
$schedule_shift->hours = $shift[ 'hours' ];
|
|
$schedule_shift->amount = $shift[ 'amount' ];
|
|
$schedule_shift->save();
|
|
$this->log( 'scheduleDriverPayment', $schedule->properties() );
|
|
}
|
|
}
|
|
if( $_driver[ 'invites' ] ){
|
|
foreach( $_driver[ 'invites' ] as $invite ){
|
|
$schedule_referral = new Cockpit_Payment_Schedule_Referral;
|
|
$schedule_referral->id_payment_schedule = $id_payment_schedule;
|
|
$schedule_referral->id_referral = $invite[ 'id_referral' ];
|
|
$schedule_referral->amount = $invite[ 'admin_credit' ];
|
|
$schedule_referral->save();
|
|
$this->log( 'scheduleReferralPayment', $schedule_referral->properties() );
|
|
}
|
|
}
|
|
}
|
|
|
|
if( $_driver[ 'orders' ] ){
|
|
foreach ( $_driver[ 'orders' ] as $order ) {
|
|
if( $type == Cockpit_Payment_Schedule::PAY_TYPE_REIMBURSEMENT ){
|
|
$order_amount = $order[ 'pay_info' ][ 'total_reimburse' ];
|
|
} else {
|
|
$order_amount = $order[ 'pay_info' ][ 'total_payment' ];
|
|
}
|
|
$schedule_order = new Cockpit_Payment_Schedule_Order;
|
|
$schedule_order->id_payment_schedule = $id_payment_schedule;
|
|
$schedule_order->id_order = $order[ 'id_order' ];
|
|
$schedule_order->amount = $order_amount;
|
|
$schedule_order->save();
|
|
}
|
|
}
|
|
|
|
$this->log( 'scheduleDriverPayment', $schedule->properties() );
|
|
$this->doDriverPayments( $id_payment_schedule );
|
|
}
|
|
}
|
|
|
|
public function scheduleDriverPayment( $id_drivers, $type ){
|
|
|
|
$this->log( 'scheduleDriversPayment', $id_drivers );
|
|
|
|
$drivers = $this->startDriver();
|
|
|
|
foreach ( $drivers as $_driver ) {
|
|
|
|
$key = intval( $_driver[ 'id_admin' ] );
|
|
|
|
if( ( $key > 0 ) && array_key_exists( $key, $id_drivers ) ){
|
|
$notes = $id_drivers[ $key ][ 'notes' ];
|
|
$adjustment = $id_drivers[ $key ][ 'adjustment' ];
|
|
$adjustment_notes = $id_drivers[ $key ][ 'adjustment_notes' ];
|
|
$id_driver = $key;
|
|
$id_admin = c::user()->id_admin;
|
|
$this->log( 'scheduleDriverPayment', [ $_driver, $notes, $adjustment, $adjustment_notes, $id_driver, $type, $id_admin ] );
|
|
$this->scheduleDriverPaymentTimeout( $_driver, $notes, $adjustment, $adjustment_notes, $id_driver, $type, $id_admin );
|
|
}
|
|
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public function doDriverErrPayments(){
|
|
$schedules = Cockpit_Payment_Schedule::q("SELECT * FROM payment_schedule WHERE status = '" . Cockpit_Payment_Schedule::STATUS_ERROR . "'");
|
|
foreach( $schedules as $_schedule ){
|
|
$id_payment_schedule = $_schedule->id_payment_schedule;
|
|
$settlement = new Crunchbutton_Settlement( $this->filters );
|
|
Cana::timeout( function() use( $settlement, $id_payment_schedule ) {
|
|
$settlement->payDriver( $id_payment_schedule );
|
|
} );
|
|
}
|
|
}
|
|
|
|
public function doDriverPayments( $id_payment_schedule = false ){
|
|
if( $id_payment_schedule ){
|
|
$this->log( 'doDriverPayments', $id_payment_schedule );
|
|
$settlement = new Crunchbutton_Settlement( $this->filters );
|
|
Cana::timeout( function() use( $settlement, $id_payment_schedule ) {
|
|
$settlement->payDriver( $id_payment_schedule );
|
|
} );
|
|
} else {
|
|
$schedule = new Cockpit_Payment_Schedule;
|
|
$lastDate = $schedule->lastDriverStatusDate();
|
|
$schedules = $schedule->driversSchedulesFromDate( $lastDate );
|
|
$settlement = new Crunchbutton_Settlement( $this->filters );
|
|
foreach( $schedules as $_schedule ){
|
|
$id_payment_schedule = $_schedule->id_payment_schedule;
|
|
Cana::timeout( function() use( $settlement, $id_payment_schedule ) {
|
|
$settlement->payDriver( $id_payment_schedule );
|
|
} );
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
public function doRestaurantPayments( $id_payment_schedule = false ){
|
|
if( $id_payment_schedule ){
|
|
return $this->payRestaurant( $id_payment_schedule );
|
|
} else {
|
|
$schedule = new Cockpit_Payment_Schedule;
|
|
$lastDate = $schedule->lastRestaurantStatusDate();
|
|
$schedules = $schedule->restaurantSchedulesFromDate( $lastDate );
|
|
foreach( $schedules as $_schedule ){
|
|
$this->payRestaurant( $_schedule->id_payment_schedule );
|
|
}
|
|
}
|
|
}
|
|
|
|
public function restaurantSummaryByIdPayment( $id_payment ){
|
|
$schedule = Cockpit_Payment_Schedule::q( 'SELECT * FROM payment_schedule WHERE id_payment = "' . $id_payment . '"' );
|
|
if( $schedule->id_payment_schedule ){
|
|
return $this->restaurantSummary( $schedule->id_payment_schedule );
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public function restaurantSummary( $id_payment_schedule ){
|
|
$schedule = Cockpit_Payment_Schedule::o( $id_payment_schedule );
|
|
if( $schedule->id_payment_schedule && $schedule->type == Cockpit_Payment_Schedule::TYPE_RESTAURANT ){
|
|
$settlement = new Settlement;
|
|
$summary = $schedule->exports();
|
|
$summary[ 'restaurant' ] = $schedule->restaurant()->name;
|
|
$summary[ 'summary_method' ] = $schedule->restaurant()->payment_type()->summary_method;
|
|
$summary[ 'summary_email' ] = $schedule->restaurant()->payment_type()->summary_email;
|
|
$summary[ 'summary_fax' ] = $schedule->restaurant()->payment_type()->summary_fax;
|
|
$summary[ 'payment_method' ] = $schedule->restaurant()->payment_type()->payment_method;
|
|
$summary[ 'type' ] = Cockpit_Payment_Schedule::TYPE_RESTAURANT;
|
|
$payment = $schedule->payment();
|
|
if( $payment->id_payment ){
|
|
$summary[ 'balanced_id' ] = $payment->balanced_id;
|
|
$summary[ 'stripe_id' ] = $payment->stripe_id;
|
|
$summary[ 'check_id' ] = $payment->check_id;
|
|
$summary[ 'summary_sent_date' ] = $payment->summary_sent_date()->format( 'M jS Y g:i:s A T' );
|
|
$summary[ 'payment_date' ] = $payment->date()->format( 'M jS Y g:i:s A T' );
|
|
}
|
|
if( $schedule->status_date ){
|
|
$summary[ 'status_date' ] = $schedule->status_date()->format( 'M jS Y g:i:s A T' );
|
|
}
|
|
$orders = $schedule->orders();
|
|
$_orders = [];
|
|
$summary[ 'orders_cash' ] = 0;
|
|
$summary[ 'orders_card' ] = 0;
|
|
$summary[ 'orders_not_included' ] = 0;
|
|
$summary[ 'orders' ] = [ 'card' => [], 'cash' => [], 'not_included' => [] ];
|
|
foreach( $orders as $order ){
|
|
$_order = $order->order();
|
|
if( $_order->id_order ){
|
|
$variables = $settlement->orderExtractVariables( $_order );
|
|
$type = $variables[ 'cash' ] ? 'cash' : 'card';
|
|
if( $type == 'cash' || ( $type == 'card' && $order->amount > 0 ) ){
|
|
if( $type == 'card' ){
|
|
$summary[ 'orders_card' ]++;
|
|
} else {
|
|
$summary[ 'orders_cash' ]++;
|
|
}
|
|
$summary[ 'orders' ][ $type ][] = [ 'id_order' => $variables[ 'id_order' ], 'name' => $variables[ 'name' ], 'total' => $variables[ 'final_price_plus_delivery_markup' ], 'date' => $variables[ 'short_date' ], 'tip' => $variables[ 'tip' ] ];
|
|
$_orders[] = $variables;
|
|
} else if ( !$order->amount ){
|
|
$summary[ 'orders_not_included' ]++;
|
|
$summary[ 'orders' ][ 'not_included' ][] = [ 'id_order' => $variables[ 'id_order' ], 'name' => $variables[ 'name' ], 'total' => $variables[ 'final_price_plus_delivery_markup' ], 'date' => $variables[ 'short_date' ], 'tip' => $variables[ 'tip' ] ];
|
|
}
|
|
}
|
|
}
|
|
$summary[ 'calcs' ] = $settlement->restaurantsProcessOrders( $_orders, true );
|
|
$summary[ 'calcs' ][ 'total_due' ] = $summary[ 'calcs' ][ 'total_due' ] + $summary[ 'adjustment' ];
|
|
$summary[ 'admin' ] = [ 'id_admin' => $schedule->id_admin, 'name' => $schedule->admin()->name ];
|
|
return $summary;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public function payRestaurant( $id_payment_schedule ){
|
|
|
|
$env = c::getEnv();
|
|
|
|
$schedule = Cockpit_Payment_Schedule::o( $id_payment_schedule );
|
|
$this->log( 'payRestaurant', $schedule->properties() );
|
|
if( $schedule->id_payment_schedule ){
|
|
|
|
if( $schedule->status == Cockpit_Payment_Schedule::STATUS_SCHEDULED ||
|
|
$schedule->status == Cockpit_Payment_Schedule::STATUS_ERROR ){
|
|
|
|
// Save the processing date
|
|
$schedule->status = Cockpit_Payment_Schedule::STATUS_PROCESSING;
|
|
$schedule->status_date = date( 'Y-m-d H:i:s' );
|
|
$schedule->save();
|
|
|
|
$amount = floatval( $schedule->amount );
|
|
|
|
$payment_method = $schedule->restaurant()->payment_type()->payment_method;
|
|
|
|
// Deposit payment method
|
|
if( $payment_method == Crunchbutton_Restaurant_Payment_Type::PAYMENT_METHOD_DEPOSIT ){
|
|
|
|
$payment_type = $schedule->restaurant()->payment_type();
|
|
|
|
if( !$payment_type->balanced_id || !$payment_type->balanced_bank ){
|
|
$schedule->log = 'There is no account info for this restaurant.';
|
|
$message = 'Restaurant Payment error! Restaurant: ' . $schedule->restaurant()->name;
|
|
$message .= "\n". 'id_payment_schedule: ' . $schedule->id_payment_schedule;
|
|
$message .= "\n". 'amount: ' . $schedule->amount;
|
|
$message .= "\n". $schedule->log;
|
|
$schedule->status = Cockpit_Payment_Schedule::STATUS_ERROR;
|
|
$schedule->status_date = date( 'Y-m-d H:i:s' );
|
|
$schedule->save();
|
|
Crunchbutton_Support::createNewWarning( [ 'body' => $message ] );
|
|
return false;
|
|
}
|
|
|
|
if( $amount > 0 ){
|
|
try {
|
|
$p = Payment::credit( [ 'id_restaurant' => $schedule->id_restaurant,
|
|
'amount' => $amount,
|
|
'note' => $schedule->note,
|
|
'type' => 'balanced' ] );
|
|
} catch ( Exception $e ) {
|
|
$schedule->log = $e->getMessage();
|
|
$schedule->status = Cockpit_Payment_Schedule::STATUS_ERROR;
|
|
$schedule->status_date = date( 'Y-m-d H:i:s' );
|
|
$schedule->save();
|
|
$this->log( 'payRestaurant: Error', $schedule->properties() );
|
|
return false;
|
|
}
|
|
} else {
|
|
$payment = new Crunchbutton_Payment;
|
|
$payment->date = date( 'Y-m-d H:i:s' );
|
|
$payment->id_restaurant = $schedule->id_restaurant;
|
|
$payment->note = $schedule->note;
|
|
$payment->env = c::getEnv();
|
|
$payment->id_admin = c::user()->id_admin;
|
|
$payment->amount = 0;
|
|
$payment->adjustment = $schedule->adjustment;
|
|
$payment->save();
|
|
|
|
$p = $payment->id_payment;
|
|
}
|
|
|
|
if( $p ){
|
|
|
|
$payment = Crunchbutton_Payment::o( $p );
|
|
// save the adjustment
|
|
if( floatval( $schedule->adjustment ) != 0 ){
|
|
$payment->adjustment = $schedule->adjustment;
|
|
$payment->save();
|
|
}
|
|
|
|
$schedule->id_payment = $payment->id_payment;
|
|
$schedule->status = Cockpit_Payment_Schedule::STATUS_DONE;
|
|
$schedule->log = 'Payment finished';
|
|
$schedule->status_date = date( 'Y-m-d H:i:s' );
|
|
$schedule->save();
|
|
$this->log( 'payRestaurant: Success', $schedule->properties() );
|
|
$orders = $schedule->orders();
|
|
|
|
foreach ( $orders as $order ) {
|
|
|
|
$order_transaction = new Crunchbutton_Order_Transaction;
|
|
$order_transaction->id_order = $order->id_order;
|
|
$order_transaction->amt = $order->amount;
|
|
$order_transaction->date = date( 'Y-m-d H:i:s' );
|
|
$order_transaction->type = Crunchbutton_Order_Transaction::TYPE_PAID_TO_RESTAURANT;
|
|
$order_transaction->source = Crunchbutton_Order_Transaction::SOURCE_CRUNCHBUTTON;
|
|
$order_transaction->id_admin = $payment->id_admin;
|
|
$order_transaction->save();
|
|
|
|
$payment_order_transaction = new Cockpit_Payment_Order_Transaction;
|
|
$payment_order_transaction->id_payment = $payment->id_payment;
|
|
$payment_order_transaction->id_order_transaction = $order_transaction->id_order_transaction;
|
|
$payment_order_transaction->save();
|
|
}
|
|
|
|
$this->sendRestaurantPaymentNotification( $payment->id_payment );
|
|
return true;
|
|
} else {
|
|
$message = 'Restaurant Payment error! Restaurant: ' . $schedule->restaurant()->name;
|
|
$message .= "\n". 'id_payment_schedule: ' . $schedule->id_payment_schedule;
|
|
$message .= "\n". 'amount: ' . $schedule->amount;
|
|
$message .= "\n". $schedule->log;
|
|
$schedule->status = Cockpit_Payment_Schedule::STATUS_ERROR;
|
|
$schedule->status_date = date( 'Y-m-d H:i:s' );
|
|
$schedule->save();
|
|
Crunchbutton_Support::createNewWarning( [ 'body' => $message ] );
|
|
return false;
|
|
}
|
|
}
|
|
// Check payment method
|
|
else if( $payment_method == Crunchbutton_Restaurant_Payment_Type::PAYMENT_METHOD_CHECK ){
|
|
|
|
$payment_type = $schedule->restaurant()->payment_type();
|
|
|
|
$check_address = $payment_type->check_address;
|
|
$check_address_city = $payment_type->check_address_city;
|
|
$check_address_state = $payment_type->check_address_state;
|
|
$check_address_zip = $payment_type->check_address_zip;
|
|
$check_address_country = $payment_type->check_address_country;
|
|
|
|
$contact_name = $payment_type->contact_name;
|
|
|
|
$error = false;
|
|
$schedule->log = '';
|
|
if( !$check_address || !$check_address_city || !$check_address_state || !$check_address_zip || !$check_address_country ){
|
|
$schedule->log = 'Check address is incomplete. ';
|
|
$error = true;
|
|
}
|
|
if( !$contact_name ){
|
|
$schedule->log .= 'Contact name is missing.';
|
|
$error = true;
|
|
}
|
|
if( $error ){
|
|
$message = 'Restaurant Payment error! Restaurant: ' . $schedule->restaurant()->name;
|
|
$message .= "\n". 'id_payment_schedule: ' . $schedule->id_payment_schedule;
|
|
$message .= "\n". 'amount: ' . $schedule->amount;
|
|
$message .= "\n". $schedule->log;
|
|
$schedule->status = Cockpit_Payment_Schedule::STATUS_ERROR;
|
|
$schedule->status_date = date( 'Y-m-d H:i:s' );
|
|
$schedule->save();
|
|
$this->log( 'payRestaurant: Error', $schedule->properties() );
|
|
Crunchbutton_Support::createNewWarning( [ 'body' => $message ] );
|
|
} else {
|
|
|
|
$check_name = $schedule->restaurant()->name;
|
|
|
|
if( $amount > 0 ){
|
|
try{
|
|
$c = c::lob()->checks()->create( [ 'name' => $check_name,
|
|
'to' => [ 'name' => $contact_name,
|
|
'address_line1' => $check_address,
|
|
'address_city' => $check_address_city,
|
|
'address_state' => $check_address_state,
|
|
'address_zip' => $check_address_zip,
|
|
'address_country' => $check_address_country ],
|
|
'bank_account' => c::lob()->defaultAccount(),
|
|
'amount' => $amount,
|
|
'memo' => $schedule->note,
|
|
'message' => $schedule->note ] );
|
|
$check_id = $c->id;
|
|
} catch( Exception $e ) {
|
|
$schedule->log = $e->getMessage();
|
|
$schedule->status = Cockpit_Payment_Schedule::STATUS_ERROR;
|
|
$schedule->status_date = date( 'Y-m-d H:i:s' );
|
|
$schedule->save();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if( $check_id || $amount == 0 ){
|
|
$success = true;
|
|
}
|
|
|
|
if( $success ){
|
|
|
|
$payment = new Crunchbutton_Payment;
|
|
$payment->check_id = $c->id;
|
|
$payment->date = date( 'Y-m-d H:i:s' );
|
|
$payment->id_restaurant = $schedule->id_restaurant;
|
|
$payment->note = $schedule->note;
|
|
$payment->env = c::getEnv();
|
|
$payment->id_admin = c::user()->id_admin;
|
|
$payment->amount = $schedule->amount;
|
|
$payment->adjustment = $schedule->adjustment;
|
|
$payment->save();
|
|
|
|
$schedule->id_payment = $payment->id_payment;
|
|
$schedule->status = Cockpit_Payment_Schedule::STATUS_DONE;
|
|
$schedule->log = 'Payment finished';
|
|
$schedule->status_date = date( 'Y-m-d H:i:s' );
|
|
$schedule->save();
|
|
|
|
$this->log( 'payRestaurant: Success', $schedule->properties() );
|
|
|
|
$orders = $schedule->orders();
|
|
|
|
foreach ( $orders as $order ) {
|
|
|
|
$order_transaction = new Crunchbutton_Order_Transaction;
|
|
$order_transaction->id_order = $order->id_order;
|
|
$order_transaction->amt = $order->amount;
|
|
$order_transaction->date = date( 'Y-m-d H:i:s' );
|
|
$order_transaction->type = Crunchbutton_Order_Transaction::TYPE_PAID_TO_RESTAURANT;
|
|
$order_transaction->source = Crunchbutton_Order_Transaction::SOURCE_CRUNCHBUTTON;
|
|
$order_transaction->id_admin = $payment->id_admin;
|
|
$order_transaction->save();
|
|
|
|
$payment_order_transaction = new Cockpit_Payment_Order_Transaction;
|
|
$payment_order_transaction->id_payment = $payment->id_payment;
|
|
$payment_order_transaction->id_order_transaction = $order_transaction->id_order_transaction;
|
|
$payment_order_transaction->save();
|
|
}
|
|
|
|
$this->sendRestaurantPaymentNotification( $payment->id_payment );
|
|
return true;
|
|
|
|
} else {
|
|
$message = 'Restaurant Payment error! Restaurant: ' . $schedule->restaurant()->name;
|
|
$message .= "\n". 'id_payment_schedule: ' . $schedule->id_payment_schedule;
|
|
$message .= "\n". 'amount: ' . $schedule->amount;
|
|
$message .= "\n". $schedule->log;
|
|
$schedule->status = Cockpit_Payment_Schedule::STATUS_ERROR;
|
|
$schedule->status_date = date( 'Y-m-d H:i:s' );
|
|
$schedule->save();
|
|
$this->log( 'payRestaurant: Error', $schedule->properties() );
|
|
Crunchbutton_Support::createNewWarning( [ 'body' => $message ] );
|
|
return false;
|
|
}
|
|
}
|
|
} else {
|
|
if( $payment_method != Crunchbutton_Restaurant_Payment_Type::PAYMENT_METHOD_NO_PAYMENT ){
|
|
$schedule->log = 'Restaurant doesn\'t have a payment method.';
|
|
$message = 'Restaurant Payment error! Restaurant: ' . $schedule->restaurant()->name;
|
|
$message .= "\n". 'id_payment_schedule: ' . $schedule->id_payment_schedule;
|
|
$message .= "\n". 'amount: ' . $schedule->amount;
|
|
$message .= "\n". $schedule->log;
|
|
$schedule->status = Cockpit_Payment_Schedule::STATUS_ERROR;
|
|
$schedule->status_date = date( 'Y-m-d H:i:s' );
|
|
$schedule->save();
|
|
$this->log( 'payRestaurant: Error', $schedule->properties() );
|
|
Crunchbutton_Support::createNewWarning( [ 'body' => $message ] );
|
|
}
|
|
}
|
|
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public function payDriver( $id_payment_schedule ){
|
|
|
|
$env = c::getEnv();
|
|
|
|
$schedule = Cockpit_Payment_Schedule::o( $id_payment_schedule );
|
|
$this->log( 'payDriver', $schedule->properties() );
|
|
if( $schedule->id_payment_schedule ){
|
|
|
|
if( !$schedule->id_payment &&
|
|
( $schedule->status == Cockpit_Payment_Schedule::STATUS_SCHEDULED ||
|
|
$schedule->status == Cockpit_Payment_Schedule::STATUS_ERROR ||
|
|
$schedule->status == Cockpit_Payment_Schedule::STATUS_ARCHIVED ) ){
|
|
|
|
// Save the processing date
|
|
$schedule->status = Cockpit_Payment_Schedule::STATUS_PROCESSING;
|
|
$schedule->status_date = date( 'Y-m-d H:i:s' );
|
|
$schedule->save();
|
|
|
|
$amount = floatval( $schedule->amount );
|
|
|
|
$payment_type = $schedule->driver()->payment_type();
|
|
|
|
$payment_method = $payment_type->payment_method;
|
|
|
|
// Deposit payment method
|
|
if( $payment_method == Crunchbutton_Admin_Payment_Type::PAYMENT_METHOD_DEPOSIT ){
|
|
|
|
if( !$payment_type->balanced_id || !$payment_type->balanced_bank ){
|
|
$schedule->log = 'There is no account info for this driver.';
|
|
$message = 'Restaurant Payment error! Driver: ' . $schedule->driver()->name;
|
|
$message .= "\n". 'id_payment_schedule: ' . $schedule->id_payment_schedule;
|
|
$message .= "\n". 'amount: ' . $schedule->amount;
|
|
$message .= "\n". $schedule->log;
|
|
$schedule->status = Cockpit_Payment_Schedule::STATUS_ERROR;
|
|
$schedule->status_date = date( 'Y-m-d H:i:s' );
|
|
$schedule->save();
|
|
return false;
|
|
}
|
|
|
|
if( $amount > 0 ){
|
|
|
|
try {
|
|
$id_payment = ( $schedule->id_payment ) ? $schedule->id_payment : null;
|
|
$p = Payment::credit_driver( [ 'id_driver' => $schedule->id_driver,
|
|
'id_payment' => $id_payment,
|
|
'amount' => $amount,
|
|
'note' => $schedule->note,
|
|
'pay_type' => $schedule->pay_type,
|
|
'type' => 'balanced' ] );
|
|
} catch ( Exception $e ) {
|
|
$schedule->log = $e->getMessage();
|
|
$schedule->status = Cockpit_Payment_Schedule::STATUS_ERROR;
|
|
$schedule->status_date = date( 'Y-m-d H:i:s' );
|
|
$schedule->save();
|
|
$this->log( 'payDriver: Error', $schedule->properties() );
|
|
return false;
|
|
}
|
|
|
|
} else {
|
|
|
|
// If the payment is 0 just create a payment register and send to the driver the summary
|
|
$payment = new Crunchbutton_Payment;
|
|
$payment->date = date( 'Y-m-d H:i:s' );
|
|
$payment->note = $schedule->note;
|
|
$payment->adjustment_note = $schedule->adjustment_note;
|
|
$payment->env = c::getEnv();
|
|
$payment->id_driver = $schedule->id_driver;
|
|
$payment->id_admin = ( c::user()->id_admin ? c::user()->id_admin : $schedule->id_driver );
|
|
$payment->amount = 0;
|
|
$payment->pay_type = $schedule->pay_type;
|
|
$payment->adjustment = $schedule->adjustment;
|
|
$payment->save();
|
|
|
|
$schedule->id_payment = $payment->id_payment;
|
|
$schedule->status = Cockpit_Payment_Schedule::STATUS_DONE;
|
|
$schedule->log = 'Payment finished';
|
|
$schedule->status_date = date( 'Y-m-d H:i:s' );
|
|
$schedule->save();
|
|
$this->log( 'payDriver: Success', $schedule->properties() );
|
|
$orders = $schedule->orders();
|
|
|
|
$p = $payment->id_payment;
|
|
|
|
}
|
|
|
|
$this->log( 'payDriver: Success id_payment', $p );
|
|
|
|
if( $p ){
|
|
|
|
$payment = Crunchbutton_Payment::o( $p );
|
|
|
|
// save the adjustment
|
|
if( floatval( $schedule->adjustment ) != 0 ){
|
|
$payment->adjustment = $schedule->adjustment;
|
|
$payment->adjustment_note = $schedule->adjustment_note;
|
|
}
|
|
|
|
// Bug fix
|
|
$payment->pay_type = $schedule->pay_type;
|
|
$payment->save();
|
|
|
|
$schedule->id_payment = $payment->id_payment;
|
|
$schedule->status = Cockpit_Payment_Schedule::STATUS_DONE;
|
|
$schedule->log = 'Payment finished';
|
|
$schedule->status_date = date( 'Y-m-d H:i:s' );
|
|
$schedule->save();
|
|
$this->log( 'payDriver: Success', $schedule->properties() );
|
|
$orders = $schedule->orders();
|
|
|
|
if( $schedule->pay_type == Cockpit_Payment_Schedule::PAY_TYPE_PAYMENT ){
|
|
$order_transaction_type = Crunchbutton_Order_Transaction::TYPE_PAID_TO_DRIVER;
|
|
} else {
|
|
$order_transaction_type = Crunchbutton_Order_Transaction::TYPE_REIMBURSED_TO_DRIVER;
|
|
}
|
|
|
|
foreach ( $orders as $order ) {
|
|
|
|
$order_transaction = new Crunchbutton_Order_Transaction;
|
|
$order_transaction->id_order = $order->id_order;
|
|
$order_transaction->amt = $order->amount;
|
|
$order_transaction->date = date( 'Y-m-d H:i:s' );
|
|
$order_transaction->type = $order_transaction_type;
|
|
$order_transaction->source = Crunchbutton_Order_Transaction::SOURCE_CRUNCHBUTTON;
|
|
$order_transaction->id_admin = $payment->id_admin;
|
|
$order_transaction->save();
|
|
|
|
$payment_order_transaction = new Cockpit_Payment_Order_Transaction;
|
|
$payment_order_transaction->id_payment = $payment->id_payment;
|
|
$payment_order_transaction->id_order_transaction = $order_transaction->id_order_transaction;
|
|
$payment_order_transaction->save();
|
|
}
|
|
|
|
$this->sendDriverPaymentNotification( $payment->id_payment );
|
|
return true;
|
|
} else {
|
|
$message = 'Driver Payment error! Driver: ' . $schedule->driver()->name;
|
|
$message .= "\n". 'id_payment_schedule: ' . $schedule->id_payment_schedule;
|
|
$message .= "\n". 'amount: ' . $schedule->amount;
|
|
$message .= "\n". $schedule->log;
|
|
$schedule->status = Cockpit_Payment_Schedule::STATUS_ERROR;
|
|
$schedule->status_date = date( 'Y-m-d H:i:s' );
|
|
$schedule->save();
|
|
$this->driverPaymentError( $schedule->id_payment_schedule );
|
|
// Crunchbutton_Support::createNewWarning( [ 'body' => $message ] );
|
|
return false;
|
|
}
|
|
} else {
|
|
$schedule->log = 'Driver doesn\'t have a payment method.';
|
|
$message = 'Driver Payment error! Driver: ' . $schedule->driver()->name;
|
|
$message .= "\n". 'id_payment_schedule: ' . $schedule->id_payment_schedule;
|
|
$message .= "\n". 'amount: ' . $schedule->amount;
|
|
$message .= "\n". $schedule->log;
|
|
$schedule->status = Cockpit_Payment_Schedule::STATUS_ERROR;
|
|
$schedule->status_date = date( 'Y-m-d H:i:s' );
|
|
$schedule->save();
|
|
$this->log( 'payDriver: Error', $schedule->properties() );
|
|
$this->driverPaymentError( $schedule->id_payment_schedule );
|
|
// Crunchbutton_Support::createNewWarning( [ 'body' => $message ] );
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public function driverPaymentError( $id_payment_schedule ){
|
|
$schedule = Cockpit_Payment_Schedule::o( $id_payment_schedule );
|
|
if( $schedule->id_payment_schedule ){
|
|
$driver = $schedule->driver();
|
|
if( $driver->id_admin ){
|
|
|
|
$first_name = Crunchbutton_Message_Sms::greeting( $driver->firstName() );
|
|
|
|
$message = $first_name . 'Hey your payment from Crunchbutton.com failed. Make sure you entered your payment info right at http://cockpit.la/drivers/docs/payment. Text if you have questions!';
|
|
if( $driver->phone ){
|
|
Crunchbutton_Message_Sms::send( [ 'from' => 'driver', 'to' => $driver->phone, 'message' => $message, 'reason' => Crunchbutton_Message_Sms::REASON_SETTLEMENT_FAIL ] );
|
|
// Crunchbutton_Support::createNewWarning( [ 'phone' => $driver->phone, 'body' => $message ] );
|
|
}
|
|
if( $driver->email ){
|
|
$mail = new Cockpit_Email_Driver_Broadcast( [ 'driver' => $driver,
|
|
'subject' => 'Hey your payment from Crunchbutton.com failed',
|
|
'message' => $message ] );
|
|
$mail->send();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public function driverSummaryByIdPayment( $id_payment ){
|
|
$schedule = Cockpit_Payment_Schedule::q( 'SELECT * FROM payment_schedule WHERE id_payment = "' . $id_payment . '"' );
|
|
if( $schedule->id_payment_schedule ){
|
|
return $this->driverSummary( $schedule->id_payment_schedule );
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public function driverSummary( $id_payment_schedule ){
|
|
$schedule = Cockpit_Payment_Schedule::o( $id_payment_schedule );
|
|
if( $schedule->id_payment_schedule && $schedule->type == Cockpit_Payment_Schedule::TYPE_DRIVER ){
|
|
$settlement = new Settlement;
|
|
$summary = $schedule->exports();
|
|
|
|
$summary[ 'adjustment' ] = floatval( $summary[ 'adjustment' ] );
|
|
$summary[ 'driver' ] = $schedule->driver()->name;
|
|
$summary[ 'summary_email' ] = $schedule->driver()->payment_type()->summary_email;
|
|
$summary[ 'driver' ] = $schedule->driver()->name;
|
|
$summary[ 'payment_method' ] = $schedule->driver()->payment_type()->payment_method;
|
|
$summary[ 'salary_type' ] = ( $schedule->driver_payment_hours ) ? Crunchbutton_Admin_Payment_Type::PAYMENT_TYPE_HOURS : Crunchbutton_Admin_Payment_Type::PAYMENT_TYPE_ORDERS;
|
|
$summary[ 'type' ] = Cockpit_Payment_Schedule::TYPE_DRIVER;
|
|
$payment = $schedule->payment();
|
|
if( $payment->id_payment ){
|
|
$summary[ 'balanced_status' ] = $payment->balanced_status;
|
|
$summary[ 'balanced_failure_reason' ] = $payment->balanced_failure_reason;
|
|
$balanced_date_checked = $payment->balanced_date_checked();
|
|
if( $balanced_date_checked ){
|
|
$summary[ 'balanced_date_checked' ] = $balanced_date_checked->format( 'M jS Y g:i:s A T' );
|
|
}
|
|
$summary[ 'balanced_id' ] = $payment->balanced_id;
|
|
$summary[ 'stripe_id' ] = $payment->stripe_id;
|
|
$summary[ 'check_id' ] = $payment->check_id;
|
|
$summary[ 'summary_sent_date' ] = $payment->summary_sent_date()->format( 'M jS Y g:i:s A T' );
|
|
$summary[ 'payment_date' ] = $payment->date()->format( 'M jS Y g:i:s A T' );
|
|
$status = Cockpit_Payment_Schedule::statusToDriver( $schedule );
|
|
$summary[ 'expected_date' ] = $status[ 'paid_date' ];
|
|
}
|
|
if( $schedule->status_date ){
|
|
$summary[ 'status_date' ] = $schedule->status_date()->format( 'M jS Y g:i:s A T' );
|
|
}
|
|
|
|
$invites = $schedule->invites();
|
|
if( $invites ){
|
|
$summary[ 'invites_count' ] = 0;
|
|
$summary[ 'invites_amount' ] = 0;
|
|
$summary[ 'invites' ] = [];
|
|
foreach( $invites as $invite ){
|
|
$_invite = $invite->referral()->settlementExport();
|
|
$_invite[ 'amount' ] = $invite->amount;
|
|
$summary[ 'invites' ][] = $_invite;
|
|
$summary[ 'invites_count' ]++;
|
|
$summary[ 'invites_amount' ] += $invite->amount;
|
|
}
|
|
}
|
|
|
|
$shifts = $schedule->shifts();
|
|
|
|
if( $shifts ){
|
|
$summary[ 'shifts_count' ] = 0;
|
|
$summary[ 'shifts_hours' ] = 0;
|
|
$summary[ 'shifts_hours_amount' ] = 0;
|
|
$summary[ 'shifts' ] = [];
|
|
foreach( $shifts as $shift ){
|
|
$_shift = [];
|
|
$_shift[ 'amount' ] = $shift->amount;
|
|
$_shift[ 'hours' ] = $shift->hours;
|
|
$_shift[ 'period' ] = $shift->shift()->startEndToStringCommunityTz();
|
|
$summary[ 'shifts' ][] = $_shift;
|
|
$summary[ 'shifts_count' ]++;
|
|
$summary[ 'shifts_hours' ] += $shift->hours;
|
|
$summary[ 'shifts_hours_amount' ] += $shift->amount;
|
|
}
|
|
}
|
|
|
|
$summary[ '_total_reimburse_' ] = 0;
|
|
$summary[ '_total_payment_' ] = 0;
|
|
$summary[ '_total_received_cash_' ] = 0;
|
|
$summary[ '_total_cash_orders_' ] = 0;
|
|
|
|
$orders = $schedule->orders();
|
|
|
|
$_orders = [];
|
|
$summary[ 'orders_count' ] = 0;
|
|
$summary[ 'orders_not_included' ] = 0;
|
|
$summary[ 'orders' ] = [ 'included' => [], 'not_included' => [] ];
|
|
foreach( $orders as $order ){
|
|
$_order = $order->order();
|
|
if( $_order->id_order ){
|
|
$variables = $settlement->orderExtractVariables( $_order );
|
|
$pay_info = $settlement->driversProcess( [ $variables ], true, false, false );
|
|
|
|
$type = $variables[ 'cash' ] ? 'Cash' : 'Card';
|
|
$summary[ 'orders_count' ]++;
|
|
|
|
$_total_payment = $pay_info[ 0 ][ 'orders' ][ 0 ][ 'pay_info' ][ 'total_payment' ];
|
|
if( is_null( $_total_payment ) ){
|
|
$_total_payment = $pay_info[ 1 ][ 'total_payment' ];
|
|
}
|
|
|
|
$_total_payment = max( 0, $_total_payment );
|
|
$_total_reimburse = max( 0, $pay_info[ 0 ][ 'total_reimburse' ] );
|
|
|
|
$summary[ 'orders' ][ 'included' ][] = [ 'id_order' => $variables[ 'id_order' ],
|
|
'name' => $variables[ 'name' ],
|
|
'total' => $variables[ 'final_price_plus_delivery_markup' ],
|
|
'date' => $variables[ 'short_date' ],
|
|
'tip' => $pay_info[0][ 'orders' ][ 0 ][ 'pay_info' ][ 'tip' ],
|
|
'restaurant' => $variables[ 'restaurant' ],
|
|
'delivery_fee' => $pay_info[0][ 'orders' ][ 0 ][ 'pay_info' ][ 'delivery_fee' ],
|
|
'pay_type' => $type,
|
|
'total_reimburse' => $_total_reimburse,
|
|
'total_payment' => $_total_payment
|
|
];
|
|
if( $type == 'Cash' ){
|
|
$summary[ '_total_received_cash_' ] = $variables[ 'final_price_plus_delivery_markup' ] + $variables[ 'delivery_fee' ];
|
|
$summary[ '_total_cash_orders_' ]++;
|
|
}
|
|
|
|
$_orders[] = $variables;
|
|
$summary[ '_total_reimburse_' ] += $pay_info[ 1 ][ 'total_reimburse' ];
|
|
$summary[ '_total_payment_' ] += $pay_info[ 1 ][ 'total_payment' ];
|
|
}
|
|
}
|
|
|
|
$calcs = $settlement->driversProcess( $_orders, true, false, ( $schedule->driver_payment_hours == 1 && $schedule->pay_type == Cockpit_Payment_Schedule::PAY_TYPE_PAYMENT ), $schedule->id_driver );
|
|
|
|
if( $schedule->driver_payment_hours > 0 ){
|
|
$calcs[ 'shifts' ] = false;
|
|
}
|
|
|
|
$total_reimburse = $calcs[ 1 ][ 'total_reimburse' ];
|
|
$total_payment = $calcs[ 1 ][ 'total_payment' ];
|
|
|
|
if( $summary[ 'pay_type' ] == Cockpit_Payment_Schedule::PAY_TYPE_PAYMENT ){
|
|
if( $schedule->driver_payment_hours ){
|
|
$total_payment = floatval( $summary[ 'amount' ] );
|
|
$summary[ 'hourly' ] = true;
|
|
}
|
|
}
|
|
|
|
$index = 0;
|
|
$summary[ 'calcs' ] = [ 'total_reimburse' => floatval( $total_reimburse ),
|
|
'total_payment' => floatval( $total_payment ),
|
|
'tax' => floatval( $calcs[ $index ][ 'tax' ] ),
|
|
'delivery_fee' => floatval( $calcs[ $index ][ 'delivery_fee' ] ),
|
|
'tip' => floatval( $calcs[ $index ][ 'tip' ] ),
|
|
'customer_fee' => floatval( $calcs[ $index ][ 'customer_fee' ] ),
|
|
'markup' => floatval( $calcs[ $index ][ 'markup' ] ),
|
|
'credit_charge' => floatval( $calcs[ $index ][ 'credit_charge' ] ),
|
|
'restaurant_fee' => floatval( $calcs[ $index ][ 'restaurant_fee' ] ),
|
|
'gift_card' => floatval( $calcs[ $index ][ 'gift_card' ] ),
|
|
'subtotal' => floatval( $calcs[ $index ][ 'subtotal' ] ),
|
|
];
|
|
|
|
$summary[ 'admin' ] = [ 'id_admin' => $schedule->id_admin, 'name' => $schedule->admin()->name ];
|
|
|
|
if( $summary[ 'pay_type' ] == Cockpit_Payment_Schedule::PAY_TYPE_PAYMENT ){
|
|
$summary[ 'total_payment' ] = max( $summary[ 'amount' ], 0 );
|
|
$summary[ 'calcs' ][ 'total_payment' ] = floatval( $summary[ 'total_payment' ] );
|
|
}
|
|
if( $summary[ 'pay_type' ] == Cockpit_Payment_Schedule::PAY_TYPE_REIMBURSEMENT ){
|
|
$summary[ 'total_reimburse' ] = max( $summary[ 'amount' ], 0 );
|
|
$summary[ 'calcs' ][ 'total_reimburse' ] = floatval( $summary[ 'total_reimburse' ] );
|
|
}
|
|
|
|
return $summary;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public function sendRestaurantPaymentNotification( $id_payment ){
|
|
|
|
$summary = $this->restaurantSummaryByIdPayment( $id_payment );
|
|
|
|
if( !$summary ){
|
|
return false;
|
|
}
|
|
|
|
$this->log( 'sendRestaurantPaymentNotification', $summary );
|
|
|
|
$env = c::getEnv();
|
|
|
|
$mail = ( $env == 'live' ? $summary[ 'summary_email' ] : Crunchbutton_Settlement::TEST_SUMMARY_EMAIL );
|
|
$fax = ( $env == 'live' ? $summary[ 'summary_fax' ] : Crunchbutton_Settlement::TEST_SUMMARY_FAX );
|
|
|
|
$mail = new Crunchbutton_Email_Payment_Summary( [ 'summary' => $summary ] );
|
|
|
|
$error = false;
|
|
|
|
switch ( $summary[ 'summary_method' ] ) {
|
|
case 'email':
|
|
if( !$summary[ 'summary_email' ] ){
|
|
$error = 'email';
|
|
}
|
|
break;
|
|
case 'fax':
|
|
if( !$summary[ 'summary_fax' ] ){
|
|
$error = 'fax';
|
|
}
|
|
break;
|
|
}
|
|
|
|
if( $error ){
|
|
$message = 'Payment Summary send error! Restaurant: ' . $summary[ 'restaurant' ];
|
|
$message .= "\n". 'id_payment_schedule: ' . $summary[ 'id_payment_schedule' ];
|
|
$message .= "\n". 'amount: ' . $summary[ 'amount' ];
|
|
$message .= "\n";
|
|
if( $error == 'email' ){
|
|
$message .= 'Summary email missing.';
|
|
} else if( $error == 'fax' ){
|
|
$message .= 'Summary fax missing.';
|
|
}
|
|
Crunchbutton_Support::createNewWarning( [ 'body' => $message ] );
|
|
return;
|
|
}
|
|
|
|
switch ( $summary[ 'summary_method' ] ) {
|
|
case 'email':
|
|
|
|
if ( $mail->send() ) {
|
|
$payment = Crunchbutton_Payment::o( $id_payment );
|
|
$payment->summary_sent_date = date('Y-m-d H:i:s');
|
|
$payment->save();
|
|
return true;
|
|
}
|
|
return false;
|
|
|
|
break;
|
|
|
|
case 'fax':
|
|
|
|
$temp = tempnam( '/tmp','fax' );
|
|
file_put_contents( $temp, $mail->message() );
|
|
rename($temp, $temp.'.html');
|
|
|
|
$fax = new Phaxio( [ 'to' => $fax, 'file' => $temp.'.html' ] );
|
|
|
|
unlink( $temp.'.html' );
|
|
|
|
if ( $fax->success ) {
|
|
$payment = Crunchbutton_Payment::o( $id_payment );
|
|
$payment->summary_sent_date = date('Y-m-d H:i:s');
|
|
$payment->save();
|
|
return true;
|
|
}
|
|
return false;
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public function driverInvites( $id_admin = false ){
|
|
$out = [];
|
|
if( $id_admin ){
|
|
$where = ' AND a.id_admin = ' . $id_admin;
|
|
} else {
|
|
$where = '';
|
|
}
|
|
$invites = Crunchbutton_Referral::q( 'SELECT r.* FROM referral r
|
|
INNER JOIN admin a ON r.id_admin_inviter = a.id_admin AND r.new_user = 1 ' . $where . '
|
|
WHERE r.id_referral NOT IN( SELECT psr.id_referral FROM payment_schedule_referral psr )' );
|
|
foreach( $invites as $invite ){
|
|
$_invite = $invite->settlementExport();
|
|
if( !$out[ $invite->id_admin_inviter ] ){
|
|
$out[ $invite->id_admin_inviter ] = [];
|
|
}
|
|
$out[ $invite->id_admin_inviter ][] = $_invite;
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
public function sendDriverPaymentNotification( $id_payment ){
|
|
|
|
$summary = $this->driverSummaryByIdPayment( $id_payment );
|
|
|
|
if( !$summary ){
|
|
return false;
|
|
}
|
|
|
|
$this->log( 'sendDriverPaymentNotification', $summary );
|
|
|
|
$env = c::getEnv();
|
|
|
|
$summary[ 'summary_email' ] = ( $env == 'live' ? $summary[ 'summary_email' ] : Crunchbutton_Settlement::TEST_SUMMARY_EMAIL );
|
|
|
|
$summary[ 'note' ] = ( $summary[ 'note' ] ? $summary[ 'note' ] : 'Payment' );
|
|
|
|
if( !$summary[ 'summary_email' ] ){
|
|
return false;
|
|
}
|
|
|
|
$mail = new Crunchbutton_Email_Payment_Summary( [ 'summary' => $summary ] );
|
|
if ( $mail->send() ) {
|
|
$payment = Crunchbutton_Payment::o( $id_payment );
|
|
$payment->summary_sent_date = date('Y-m-d H:i:s');
|
|
$payment->save();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public function id_order_start(){
|
|
if( !$this->_id_order_start ){
|
|
$id_order = Crunchbutton_Config::getVal( Crunchbutton_Settlement::CONFIG_KEY_ID_ORDER_START );
|
|
$this->_id_order_start = intval( $id_order );
|
|
}
|
|
return $this->_id_order_start;
|
|
}
|
|
|
|
public function checkPaymentStatus( $type = 'driver' ){
|
|
// get all payments with pending status - drivers
|
|
$payments = Crunchbutton_Payment::q( "SELECT p.* FROM payment_schedule ps INNER JOIN payment p ON ps.id_payment = p.id_payment WHERE ps.status = '" . Cockpit_Payment_Schedule::STATUS_DONE . "' AND ps.type = '{$type}' AND ( p.balanced_status != '" . Crunchbutton_Payment::BALANCED_STATUS_SUCCEEDED . "' OR p.balanced_status IS NULL ) " );
|
|
foreach( $payments as $payment ){
|
|
$id_payment = $payment->id_payment;
|
|
Cana::timeout( function() use( $id_payment ) {
|
|
$payment = Crunchbutton_Payment::o( $id_payment );
|
|
$status = $payment->checkBalancedStatus();
|
|
} );
|
|
$message = 'id_payment : ' . $payment->id_payment;
|
|
$this->log( 'checkPaymentStatus', $message );
|
|
}
|
|
}
|
|
|
|
public function checkSucceededPaymentStatus( $type = 'driver' ){
|
|
$payments = Crunchbutton_Payment::q( "SELECT p.* FROM payment_schedule ps INNER JOIN payment p ON ps.id_payment = p.id_payment WHERE ps.status = '" . Cockpit_Payment_Schedule::STATUS_DONE . "' AND ps.type = '{$type}' AND p.balanced_status = '" . Crunchbutton_Payment::BALANCED_STATUS_SUCCEEDED . "' AND p.balanced_status IS NOT NULL AND DATE( p.balanced_date_checked ) = DATE( DATE_SUB( NOW(), INTERVAL 14 day) );" );
|
|
foreach( $payments as $payment ){
|
|
$id_payment = $payment->id_payment;
|
|
Cana::timeout( function() use( $id_payment ) {
|
|
$payment = Crunchbutton_Payment::o( $id_payment );
|
|
$status = $payment->checkBalancedStatus();
|
|
} );
|
|
$message = 'id_payment : ' . $payment->id_payment;
|
|
$this->log( 'checkPaymentStatus', $message );
|
|
}
|
|
}
|
|
|
|
public function shifts( $id_driver = 0 ){
|
|
$where = ( $id_driver == 0 ) ? '' : ' AND asa.id_admin = ' . $id_driver;
|
|
return Crunchbutton_Community_Shift::q( "SELECT DISTINCT(asa.id_admin), a.name, apt.using_pex, apt.using_pex_date
|
|
FROM community_shift cs
|
|
INNER JOIN admin_shift_assign asa ON cs.id_community_shift = asa.id_community_shift
|
|
INNER JOIN admin_payment_type apt ON apt.id_admin = asa.id_admin AND apt.payment_type = 'hours'
|
|
INNER JOIN admin a ON a.id_admin = asa.id_admin
|
|
WHERE
|
|
DATE_FORMAT(cs.date_start, '%m/%d/%Y') >= '" . (new DateTime($this->filters['start']))->format('m/d/Y') . "'
|
|
AND
|
|
DATE_FORMAT(cs.date_start, '%m/%d/%Y') <= '" . (new DateTime($this->filters['end']))->format('m/d/Y') . "'"
|
|
. $where );
|
|
}
|
|
|
|
public function amount_per_invited_user(){
|
|
if( !$this->_amount_per_invited_user ){
|
|
$reward = new Crunchbutton_Reward;
|
|
$this->amount_per_invited_user = $reward->adminRefersNewUserCreditAmount();
|
|
}
|
|
return $this->amount_per_invited_user;
|
|
}
|
|
|
|
private function log( $method, $message ){
|
|
Log::debug( [ 'method' => $method, 'id_admin' => c::user()->id_admin, 'message' => $message, 'env' => c::getEnv(), 'type' => 'settlement' ] );
|
|
}
|
|
|
|
public function revertPaymentByPaymentId( $id_payment ){
|
|
$schedule = Cockpit_Payment_Schedule::q( 'SELECT * FROM payment_schedule WHERE id_payment = "' . $id_payment . '" LIMIT 1' );
|
|
if( $schedule->id_payment_schedule ){
|
|
Crunchbutton_Settlement::revertPaymentByScheduleId( $schedule->id_payment_schedule );
|
|
}
|
|
}
|
|
|
|
public function revertPaymentByScheduleId( $id_payment_schedule ){
|
|
$schedule = Cockpit_Payment_Schedule::o( $id_payment_schedule );
|
|
if( $schedule->id_payment_schedule ){
|
|
c::db()->query( 'DELETE FROM payment_schedule_order WHERE id_payment_schedule = "' . $schedule->id_payment_schedule . '"' );
|
|
c::db()->query( 'DELETE FROM payment_schedule_referral WHERE id_payment_schedule = "' . $schedule->id_payment_schedule . '"' );
|
|
c::db()->query( 'DELETE FROM payment_schedule_shift WHERE id_payment_schedule = "' . $schedule->id_payment_schedule . '"' );
|
|
if( $schedule->id_payment ){
|
|
$transactions = Crunchbutton_Order_Transaction::q( 'SELECT * FROM payment_order_transaction WHERE id_payment = "' . $schedule->id_payment . '"' );
|
|
foreach ( $transactions as $transaction ) {
|
|
c::db()->query( 'DELETE FROM order_transaction WHERE id_order_transaction = "' . $transaction->id_order_transaction . '"' );
|
|
}
|
|
c::db()->query( 'DELETE FROM payment_order_transaction WHERE id_payment = "' . $schedule->id_payment . '"' );
|
|
c::db()->query( 'DELETE FROM payment WHERE id_payment = "' . $schedule->id_payment . '"' );
|
|
}
|
|
c::db()->query( 'DELETE FROM payment_schedule WHERE id_payment_schedule = "' . $schedule->id_payment_schedule . '"' );
|
|
}
|
|
}
|
|
}
|