implement additional payment math in Settlement.php #2250
This commit is contained in:
parent
7e14838aa3
commit
9ee4c78909
@ -1,3 +0,0 @@
|
||||
ALTER TABLE `payment` ADD `id_admin` int(11) unsigned DEFAULT NULL;
|
||||
ALTER TABLE `payment` ADD KEY `payment_ibfk_2` (`id_admin`);
|
||||
ALTER TABLE `payment` ADD CONSTRAINT `payment_ibfk_2` FOREIGN KEY (`id_admin`) REFERENCES `admin` (`id_admin`) ON DELETE SET NULL ON UPDATE SET NULL
|
||||
45
db/migrate/000194_settlement.sql
Normal file
45
db/migrate/000194_settlement.sql
Normal file
@ -0,0 +1,45 @@
|
||||
-- Settlement stuff
|
||||
|
||||
-- payment_schedule - new table
|
||||
CREATE TABLE `payment_schedule` (
|
||||
`id_payment_schedule` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`id_restaurant` int(11) unsigned DEFAULT NULL,
|
||||
`id_driver` int(11) unsigned DEFAULT NULL,
|
||||
`date` datetime DEFAULT NULL,
|
||||
`amount` float DEFAULT NULL,
|
||||
`note` varchar(255) DEFAULT '',
|
||||
`payment_method` enum('deposit','check') DEFAULT NULL,
|
||||
`type` enum('restaurant','driver') DEFAULT NULL,
|
||||
`status` enum('scheduled','processing','done','error') DEFAULT NULL,
|
||||
`status_date` datetime DEFAULT NULL,
|
||||
`stripe_id` varchar(255) DEFAULT NULL,
|
||||
`balanced_id` varchar(255) DEFAULT NULL,
|
||||
`id_admin` int(11) unsigned DEFAULT NULL,
|
||||
PRIMARY KEY (`id_payment_schedule`),
|
||||
KEY `id_restaurant` (`id_restaurant`),
|
||||
KEY `payment_schedule_ibfk_2` (`id_admin`),
|
||||
KEY `payment_schedule_ibfk_3` (`id_driver`),
|
||||
CONSTRAINT `payment_schedule_ibfk_1` FOREIGN KEY (`id_restaurant`) REFERENCES `restaurant` (`id_restaurant`) ON DELETE SET NULL ON UPDATE CASCADE,
|
||||
CONSTRAINT `payment_schedule_ibfk_2` FOREIGN KEY (`id_admin`) REFERENCES `admin` (`id_admin`) ON DELETE SET NULL ON UPDATE SET NULL,
|
||||
CONSTRAINT `payment_schedule_ibfk_3` FOREIGN KEY (`id_driver`) REFERENCES `admin` (`id_admin`) ON DELETE SET NULL ON UPDATE SET NULL
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `payment_schedule_order` (
|
||||
`id_payment_schedule_order` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`id_payment_schedule` int(11) unsigned DEFAULT NULL,
|
||||
`id_order` int(11) unsigned DEFAULT NULL,
|
||||
PRIMARY KEY (`id_payment_schedule_order`),
|
||||
KEY `id_payment_schedule` (`id_payment_schedule`),
|
||||
KEY `payment_schedule_order_ibfk_2` (`id_order`),
|
||||
CONSTRAINT `payment_schedule_order_ibfk_1` FOREIGN KEY (`id_payment_schedule`) REFERENCES `payment_schedule` (`id_payment_schedule`) ON DELETE SET NULL ON UPDATE CASCADE,
|
||||
CONSTRAINT `payment_schedule_order_ibfk_2` FOREIGN KEY (`id_order`) REFERENCES `order` (`id_order`) ON DELETE SET NULL ON UPDATE SET NULL
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
|
||||
|
||||
|
||||
-- order table
|
||||
ALTER TABLE `order` ADD `reimburse_cash_order` tinyint(11) unsigned DEFAULT 0;
|
||||
|
||||
-- payment table
|
||||
ALTER TABLE `payment` ADD `id_admin` int(11) unsigned DEFAULT NULL;
|
||||
ALTER TABLE `payment` ADD KEY `payment_ibfk_2` (`id_admin`);
|
||||
ALTER TABLE `payment` ADD CONSTRAINT `payment_ibfk_2` FOREIGN KEY (`id_admin`) REFERENCES `admin` (`id_admin`) ON DELETE SET NULL ON UPDATE SET NULL
|
||||
@ -49,6 +49,9 @@ class Controller_api_settlement extends Crunchbutton_Controller_RestAccount {
|
||||
case 'pay-if-refunded':
|
||||
$this->_restaurantPayIfRefunded();
|
||||
break;
|
||||
case 'schedule':
|
||||
$this->_restaurantSchedule();
|
||||
break;
|
||||
default:
|
||||
$this->_error();
|
||||
break;
|
||||
@ -72,6 +75,20 @@ class Controller_api_settlement extends Crunchbutton_Controller_RestAccount {
|
||||
}
|
||||
}
|
||||
|
||||
private function _restaurantSchedule(){
|
||||
$start = $this->request()['start'];
|
||||
$end = $this->request()['end'];
|
||||
$_id_restaurants = explode( ',', $this->request()['id_restaurants'] );
|
||||
$id_restaurants = [];
|
||||
foreach ( $_id_restaurants as $key => $val ) {
|
||||
$id_restaurants[ trim( $val ) ] = true;
|
||||
}
|
||||
$pay_type = ( $this->request()['pay_type'] == 'all' ) ? '' : $this->request()['pay_type'];
|
||||
$settlement = new Settlement( [ 'payment_method' => $pay_type, 'start' => $start, 'end' => $end ] );
|
||||
$settlement->schedule_payment( $id_restaurants );
|
||||
echo json_encode( [ 'success' => true ] );
|
||||
}
|
||||
|
||||
private function _restaurantPayIfRefunded(){
|
||||
$id_order = $this->request()['id_order'];
|
||||
$pay_if_refunded = $this->request()['pay_if_refunded'];
|
||||
|
||||
22
include/library/Cockpit/Payment/Schedule.php
Normal file
22
include/library/Cockpit/Payment/Schedule.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
class Cockpit_Payment_Schedule extends Cana_Table {
|
||||
|
||||
const TYPE_RESTAURANT = 'restaurant';
|
||||
const TYPE_DRIVER = 'driver';
|
||||
|
||||
const STATUS_SCHEDULED = 'scheduled';
|
||||
const STATUS_PROCESSING = 'processing';
|
||||
const STATUS_DONE = 'done';
|
||||
const STATUS_ERROR = 'error';
|
||||
|
||||
public function __construct($id = null) {
|
||||
parent::__construct();
|
||||
$this->table('payment_schedule')->idVar('id_payment_schedule')->load($id);
|
||||
}
|
||||
|
||||
public function orders() {
|
||||
return Cockpit_Payment_Schedule_Order::q( 'SELECT * FROM payment_schedule_order WHERE id_payment_schedule = "' . $this->id_payment_schedule . '"' );
|
||||
}
|
||||
|
||||
}
|
||||
26
include/library/Cockpit/Payment/Schedule/Order.php
Normal file
26
include/library/Cockpit/Payment/Schedule/Order.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
class Cockpit_Payment_Schedule_Order extends Cana_Table {
|
||||
public function __construct($id = null) {
|
||||
parent::__construct();
|
||||
$this->table('payment_schedule_order')->idVar('id_payment_schedule_order')->load($id);
|
||||
}
|
||||
public function payment_schedule() {
|
||||
return Cockpit_Payment_Schedule::o($this->id_payment_schedule);
|
||||
}
|
||||
|
||||
public function checkOrderWasPaidRestaurant( $id_order ){
|
||||
$query = 'SELECT * FROM payment_schedule_order pso
|
||||
INNER JOIN payment_schedule ps ON ps.id_payment_schedule = pso.id_payment_schedule AND ps.type = "' . Cockpit_Payment_Schedule::TYPE_RESTAURANT . '"
|
||||
WHERE pso.id_order = "' . $id_order . '" LIMIT 1';
|
||||
$order = Cockpit_Payment_Schedule_Order::q( $query );
|
||||
if( $order->id_payment_schedule_order ){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function order() {
|
||||
return Cockpit_Order::o($this->order);
|
||||
}
|
||||
}
|
||||
@ -67,7 +67,7 @@ class Crunchbutton_Settlement extends Cana_Model {
|
||||
foreach ( $orders as $order ) {;
|
||||
if( $order ){
|
||||
// Pay if Refunded
|
||||
if( $order[ 'refunded' ] == 1 && $order[ 'pay_if_refunded' ] == 0 ){
|
||||
if( ( $order[ 'refunded' ] == 1 && $order[ 'pay_if_refunded' ] == 0 ) || $order[ 'restaurant_paid' ] ){
|
||||
continue;
|
||||
}
|
||||
$pay[ 'card_subtotal' ] += $this->orderCardSubtotalPayment( $order );
|
||||
@ -335,6 +335,8 @@ class Crunchbutton_Settlement extends Cana_Model {
|
||||
$values[ 'pay_if_refunded' ] = ( $order->pay_if_refunded > 0 ) ? 1: 0;
|
||||
$values[ 'reimburse_cash_order' ] = ( $order->reimburse_cash_order > 0 ) ? 1: 0;
|
||||
|
||||
$values[ 'restaurant_paid' ] = Cockpit_Payment_Schedule_Order::checkOrderWasPaidRestaurant( $order->id_order );
|
||||
|
||||
// convert all to float -> mysql returns some values as string
|
||||
foreach( $values as $key => $val ){
|
||||
$values[ $key ] = floatval( $val );
|
||||
@ -354,4 +356,49 @@ class Crunchbutton_Settlement extends Cana_Model {
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
public function schedule_payment( $id_restaurants ){
|
||||
$restaurants = $this->startRestaurant();
|
||||
foreach ( $restaurants as $_restaurant ) {
|
||||
// todo: build a better way to filter - this way is very ugly
|
||||
if( !$id_restaurants[ $_restaurant->id_restaurant ] ){
|
||||
continue;
|
||||
}
|
||||
$id_restaurant = $_restaurant->id_restaurant;
|
||||
$payment_data = $_restaurant->payment_data;
|
||||
|
||||
// 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 ){
|
||||
$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 = min( $payment_data[ 'total_due' ], 0 );
|
||||
$schedule->payment_method = $_restaurant->payment_type()->payment_method;
|
||||
$schedule->type = Cockpit_Payment_Schedule::TYPE_RESTAURANT;
|
||||
$schedule->status = Cockpit_Payment_Schedule::STATUS_SCHEDULED;
|
||||
$schedule->status_date = date( 'Y-m-d H:i:s' );
|
||||
$schedule->id_admin = c::user()->id_admin;
|
||||
$schedule->save();
|
||||
$id_payment_schedule = $schedule->id_payment_schedule;
|
||||
// save the orders
|
||||
foreach ( $_restaurant->_payableOrders as $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->save();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -91,6 +91,9 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<button class="button save" ng-click="schedule();">Begin</button>
|
||||
|
||||
</div>
|
||||
|
||||
<div ng-repeat="restaurant in result.restaurants">
|
||||
@ -157,7 +160,7 @@
|
||||
|
||||
<h3 class="title">
|
||||
<span class="link" ng-if="!restaurant.show_orders" ng-click="restaurant.show_orders = true">Show orders</span>
|
||||
<span class="link" ng-if="restaurant.show_orders" ng-click="restaurant.show_orders = false">Hide orders</span> (total {{restaurant.orders_count}} orders <span class="orange" ng-if="restaurant.refunded_count > 0"><strong> + {{restaurant.refunded_count}} </strong> refunded and not included order(s)</span> )
|
||||
<span class="link" ng-if="restaurant.show_orders" ng-click="restaurant.show_orders = false">Hide orders</span> (total {{restaurant.orders_count}} orders <span class="orange" ng-if="restaurant.not_included > 0"><strong> + {{restaurant.not_included}} </strong> refunded and not included order(s)</span> )
|
||||
</h3>
|
||||
|
||||
<table class="tb-grid tb-zebra" ng-if="restaurant.show_orders">
|
||||
@ -168,29 +171,32 @@
|
||||
<td class="td-medium">Name</td>
|
||||
<td>Amount</td>
|
||||
<td>Payment</td>
|
||||
<td>Refunded</td>
|
||||
<td></td>
|
||||
<td class="td-medium">Date</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="order in restaurant.orders" ng-class="{ 'excluded': !order.included }">
|
||||
<tr ng-repeat="order in restaurant.orders">
|
||||
<td></td>
|
||||
<td>{{order.id_order}}</td>
|
||||
<td>{{order.name}}</td>
|
||||
<td>$ {{order.total | formatPrice}}</td>
|
||||
<td>{{order.pay_type}}</td>
|
||||
<td ng-class="{ 'refunded': order.refunded }">
|
||||
<span ng-if="order.refunded">Refunded</span>
|
||||
</td>
|
||||
<td ng-class="{ 'excluded': !order.included }">{{order.id_order}}</td>
|
||||
<td ng-class="{ 'excluded': !order.included }">{{order.name}}</td>
|
||||
<td ng-class="{ 'excluded': !order.included }">$ {{order.total | formatPrice}}</td>
|
||||
<td ng-class="{ 'excluded': !order.included }">{{order.pay_type}}</td>
|
||||
<td ng-class="{ 'excluded': !order.included }">{{order.date}}</td>
|
||||
<td>
|
||||
<span ng-if="order.refunded" ng-class="{ 'pay-if-refunded': order.pay_if_refunded }" class="pointer">
|
||||
<i ng-click="pay_if_refunded( order.id_order, 0 )" ng-if="order.pay_if_refunded" class="fa fa-check-square-o"></i>
|
||||
<i ng-click="pay_if_refunded( order.id_order, 1 )" ng-if="!order.pay_if_refunded" class="fa fa-square-o"></i>
|
||||
<span ng-if="order.refunded">
|
||||
<span class="pointer orange" ng-click="pay_if_refunded( order.id_order, 1 )" ng-if="!order.pay_if_refunded">
|
||||
<i class="fa fa-square-o"></i> Refunded. Include?
|
||||
</span>
|
||||
<span class="pointer" ng-click="pay_if_refunded( order.id_order, 0 )" ng-if="order.pay_if_refunded">
|
||||
<i class="fa fa-check-square-o"></i> Refunded. Included!
|
||||
</span>
|
||||
</span>
|
||||
</td>
|
||||
<td>{{order.date}}</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@ -90,13 +90,32 @@ NGApp.controller('SettlementRestaurantsCtrl', function ( $scope, $filter, Settle
|
||||
break;
|
||||
}
|
||||
}
|
||||
$scope.unBusy();
|
||||
} else {
|
||||
$scope.result = json;
|
||||
}
|
||||
$scope.showForm = false;
|
||||
$scope.isSearching = false;
|
||||
$scope.summary();
|
||||
$scope.unBusy();
|
||||
} );
|
||||
}
|
||||
|
||||
$scope.schedule = function(){
|
||||
$scope.makeBusy();
|
||||
var id_restaurants = new Array();
|
||||
for( x in $scope.result.restaurants ){
|
||||
if( $scope.result.restaurants[ x ].pay ){
|
||||
id_restaurants.push( $scope.result.restaurants[ x ].id_restaurant );
|
||||
}
|
||||
}
|
||||
id_restaurants = id_restaurants.join( ',' );
|
||||
|
||||
var params = { 'start': $filter( 'date' )( $scope.range.start, 'yyyy-MM-dd' ),
|
||||
'end': $filter( 'date' )( $scope.range.end, 'yyyy-MM-dd' ),
|
||||
'pay_type': $scope.pay_type, 'id_restaurants' : id_restaurants };
|
||||
|
||||
SettlementService.restaurants.schedule( params, function( json ){
|
||||
$scope.begin();
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
@ -10,7 +10,8 @@ NGApp.factory( 'SettlementService', function( $resource ) {
|
||||
'range' : { 'method': 'GET', params : { action: 'range' } },
|
||||
'begin' : { 'method': 'POST', params : { action: 'begin' } },
|
||||
'restaurant' : { 'method': 'POST', params : { action: 'restaurant' } },
|
||||
'pay_if_refunded' : { 'method': 'POST', params : { action: 'pay-if-refunded' } }
|
||||
'pay_if_refunded' : { 'method': 'POST', params : { action: 'pay-if-refunded' } },
|
||||
'schedule' : { 'method': 'POST', params : { action: 'schedule' } }
|
||||
} );
|
||||
|
||||
settlement.drivers = $resource( App.service + 'settlement/drivers/:action/', { action: '@action' }, {
|
||||
@ -24,6 +25,12 @@ NGApp.factory( 'SettlementService', function( $resource ) {
|
||||
} );
|
||||
}
|
||||
|
||||
service.restaurants.schedule = function( params, callback ){
|
||||
settlement.restaurants.schedule( params, function( json ){
|
||||
callback( json );
|
||||
} );
|
||||
}
|
||||
|
||||
service.restaurants.pay_if_refunded = function( params, callback ){
|
||||
settlement.restaurants.pay_if_refunded( params, function( json ){
|
||||
callback( json );
|
||||
|
||||
@ -202,7 +202,15 @@ p {
|
||||
font-size: 1.2em;
|
||||
line-height: 1.6em;
|
||||
}
|
||||
|
||||
.orange{
|
||||
color: $orange;
|
||||
}
|
||||
.green{
|
||||
color: $green;
|
||||
}
|
||||
.excluded{
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -760,17 +768,14 @@ input {
|
||||
background: #F5F5F5;
|
||||
}
|
||||
|
||||
.tb-zebra .not-included {
|
||||
.tb-zebra .excluded {
|
||||
color: #CCC;
|
||||
font-style: italic;
|
||||
}
|
||||
.excluded{
|
||||
text-decoration: line-through;
|
||||
}
|
||||
.tb-zebra .refunded{
|
||||
color:$orange;
|
||||
font-style: normal;
|
||||
text-decoration: none !important;
|
||||
text-decoration: underline !important;
|
||||
}
|
||||
|
||||
.tb-hack tbody {
|
||||
@ -849,15 +854,15 @@ input {
|
||||
}
|
||||
|
||||
.link{
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.tb-grid .schedule-period{
|
||||
font-weight:bold;
|
||||
}
|
||||
@ -1476,13 +1481,16 @@ body.loading .loader-wrap {
|
||||
background: rgba(0,0,0,.5);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
b, strong{ font-weight: bold; }
|
||||
|
||||
.pointer{
|
||||
cursor: pointer;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.box-content {
|
||||
background: #fff;
|
||||
@ -1536,7 +1544,4 @@ b, strong{ font-weight: bold; }
|
||||
background:#dff0d8;
|
||||
color: #64763d;
|
||||
border:1px solid #d6e9c6;
|
||||
}
|
||||
.orange{
|
||||
color: $orange;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user