implement additional payment math in Settlement.php #2250

This commit is contained in:
Daniel Camargo 2014-06-13 15:01:12 -03:00
parent 7e14838aa3
commit 9ee4c78909
10 changed files with 234 additions and 43 deletions

View File

@ -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

View 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

View File

@ -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'];

View 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 . '"' );
}
}

View 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);
}
}

View File

@ -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();
}
}
}
}
}

View File

@ -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>

View File

@ -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();
} );
}

View File

@ -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 );

View File

@ -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;
}
}