I have an array of admission and each student has multiple entry of payment.
Like Admission=[1,2,3,4,5,6] this is admission ids,
and Payment=[[1->1,5,6,2],[2->2,3],[3->4,7,8] this is admission id->payment_ids
foreach($admission as $a)
{
$payment=DB::table('payement')->where('admission_id',$a->admission_id)->get();
foreach($payment as $p)
{
// Here i wan if payment_date <= today_date
// 1. Add all payment
// 2. Else Go to the next admission id
}
}
It sounds like you're looking for something like this:
foreach($admission as $a)
{
$payment = DB::table('payment')->where('admission_id', $a->admission_id)->get();
$totalPayment = 0;
foreach($payment as $p)
{
if (\Carbon\Carbon::parse($p->payment_date)->lessThanOrEqualTo(\Carbon\Carbon::now())) {
$totalPayment += $p->amount;
}
}
}
Inside of the foreach loop on $payment the code above uses Carbon to compare the dates. It looks like you're using Laravel's Eloquent so you should have Carbon available in your application since it's a Laravel dependency. I use Carbon to compare the dates because it knows more about dates than I do.
Next, if it's true that payment_date is less than or equal to the current date then it will add it to the $totalPayment for that admission. Otherwise, it will move onto the next payment. This presumably makes using continue or break unnecessary unless I am misunderstanding something.
I'm not sure what you want to do with $totalPayment. Right now it will be calculated for each admission and then lost.
If you want to find the total payment across all admissions you should move $totalPayment = 0 to the line above foreach($admission as $a).
If you want to find the total payment for each admission you could set a totalPayment on each admission $a->total_payment = $totalPayment. I would then change $totalPayment = 0 to $a->total_payment = 0 and change $totalPayment += $p->amount to $a->totalPayment += $p->amount.
Related
What I want to do is create an automatic order number. So like this date-number of order
So the first order of today would be
20190719-01
second-order of today would be
20190719-02
etc.
Then tomorrow it needs to be like 20190720-01 20190720-02 etc and so on.
How can I achieve this? preferably in PHP
str_pad() is your friend here.
$range = range(1,10);
$period = new DatePeriod(
new DateTime('2019-07-17'),
new DateInterval('P1D'),
new DateTime('2019-07-20')
);
foreach ($period as $key => $value) {
foreach($range as $inc){
$seq = str_pad($inc,2,"0",STR_PAD_LEFT);
$order_number = $value->format('Ymd').'-'.$seq;
echo $order_number.PHP_EOL;
}
echo PHP_EOL."===========".PHP_EOL;
}
WORKING DEMO: https://3v4l.org/R5POt
Normally order numbers would be sequential, and can therefore easily be derived from the AUTO INCREMENT field. In your case this is not so easy.
You could start by getting the highest AUTO INCREMENT field from the database for all orders before today:
SELECT MAX(id) FROM orders WHERE DATE(orderDate) < CURDATE();
Let us call this id $offsetId. If no orders exist yet it should be zero.
Then first insert the order information into the database, so you can get the id of that order. You can do this either with $con->insert_id in MySQLi or lastInsertId() in PDO. let's call this the $orderId.
The reason, to use a database in this way, is to prevent that two orders ever get the same order number.
Now you can compute the order number for today:
$orderNumber = date("Ymd") . "-" . sprintf('%02d', $orderId - $offsetId);
And you can store this in the database, with the order.
You should probably anticipate more than 99 orders a day...
I am trying to get the total amount collected in a month, let's say January.
I am able to retrieve all the created_at fields which were created in the month of January in the $main_data_January variable. The $main_data_January variable contains this type of results.
As you can see, each item has a field called amount.
Problem
I want to retrieve the value of amount field from each item and sum them up. As I'm doing it in the total_earnings_janunary, but this is where I am facing the problem.
By adding both the amounts, the expected result should be 13000, but
the result is 8000. It is only getting only the first value of amount after being in a loop.
$customers = Tag::all();
$total_earnings_janunary = 0;
$query_date = '2017-01-04';
$start_date_janunary = date('Y-01-01', strtotime($query_date));
$end_date_janunary = date('Y-m-t', strtotime($query_date));
foreach ($customers as $customer) {
if (Auth::User()->gym_code == $customer->gym_code ) {
$main_data_janunarys = DB::table('tags')->whereBetween('created_at', [$start_date_janunary,$end_date_janunary])->get();
}
}
for ($i=0; $i <= count($main_data_janunarys); $i++) {
$total_earnings_janunary = $total_earnings_janunary + $main_data_janunarys[$i]->amount;
dd($total_earnings_janunary);
}
Few things to note:
You're querying the Tag model and storing it in $customers. Resulting entities are not customers. Make sure that's intended.
In the first foreach loop, you are overwriting previous value of the $main_data_janunarys over and over. Use break if that's intended.
In the for loop, you are dding early. Move it outside the loop and you'll see your intended results. In the loop exit condition you should be using < instead of <= as you're starting from zero.
To sum up the collection you could just use Collection::sum() method, like: $main_data_janunarys->sum('amount');.
Try this:
$customers = Tag::all();
$total_earnings_janunary = 0;
$query_date = '2017-01-04';
$start_date_janunary = date('Y-01-01', strtotime($query_date));
$end_date_janunary = date('Y-m-t', strtotime($query_date));
foreach ($customers as $customer)
{
if( Auth::User()->gym_code == $customer->gym_code ) {
$main_data_janunarys = DB::table('tags')->whereBetween('created_at', [$start_date_janunary,$end_date_janunary])->get();
}
}
$total_earnings_january = $main_data_januarys->sum('amount');
You can read further about Laravel's Collection here
I am trying to query for all payments assigned to an invoice using the consolibyte quickbooks php toolkit. I was hoping I could pull these back using a query but so far the only way I can see to do it is by grabbing all payments and then looping through and checking what is within the LinkedTxn array and checking if it has a type of 'Invoice' and that the 'TxnId' value matches my stored invoice id. What I have so far is this which gets the payments but is obviously not an option going forward as there may be tens of thousands of payments in the system:
public function getAllPaymentsForInvoice(Invoice $invoice)
{
$query = "SELECT * FROM Payment";
$payments = $this->qbPaymentService->query($this->context, $this->realm, $query);
$lines = [];
foreach ($payments as $payment) {
$num_lines = $payment->countLine();
for ($i = 0; $i < $num_lines; $i++) {
$line = $payment->getLine($i);
$txnId = $this->parseResponse($line->getLinkedTxn()->getTxnId());// convert {-1} to 1
$txnType = $line->getLinkedTxn()->getTxnType();
if ($txnType == 'Invoice' && $txnId == $invoice->qb_ref) {
$lines[] = $line;
}
}
}
return $lines;
}
Can anyone push me in the direction of a better way?
There's no easy, one-liner way to do this using the QuickBooks Online API. This just isn't something that QuickBooks Online itself supports.
There are two separate approaches you could take to optimize what you're doing.
The payments applied should always be for the same customer as the invoices, so you can change your query to SELECT * FROM Payment WHERE CustomerRef = 'xyz' where xyz is the CustomerRef from the invoice. Then, use your existing code to check exactly which invoices payments are applied to.
Use the CDC functionality to keep a cached copy of all payments in your own database, and query your own database for the information instead (a normal SQL database is considerably more flexible and query-able than what QuickBooks Online offers).
The CDC functionality is specifically designed to allow you to keep an accurate, cached copy of the QuickBooks data in your own application, specifically to address situations like you're running into. You pass it a timestamp, and it gives you everything that has changed since that timestamp. By remembering the date/time you last ran the ->cdc(...) method, you can continually get lightweight updates to any objects that have changed since you last queried them.
<?php
$CDCService = new QuickBooks_IPP_Service_ChangeDataCapture();
// What types of objects do you want to get?
$objects = array(
'Payment',
'Invoice',
);
// The date they should have been updated after
$timestamp = QuickBooks_Utilities::datetime($datetime_you_last_called_cdc_method);
$cdc = $CDCService->cdc($Context, $realm,
$objects,
$timestamp);
// You would cache all the stuff you get back here
print_r($cdc);
Docs links:
https://github.com/consolibyte/quickbooks-php/blob/master/docs/partner_platform/example_app_ipp_v3/example_cdc.php
https://developer.intuit.com/docs/0100_accounting/0300_developer_guides/change_data_capture
The question is quite old, anyway, in case someone else is looking for answer:
$InvoiceService = new QuickBooks_IPP_Service_Invoice();
// $invoices = $InvoiceService->query($Context, $realm, "SELECT * FROM Invoice STARTPOSITION 1 MAXRESULTS 10");
// If, we have QB Invoice # i.e.DocNumber
$invoice_no = 1001;
$invoices = $InvoiceService->query($Context, $realm, "SELECT * FROM Invoice WHERE DocNumber = '$invoice_no' ");
foreach ($invoices as $Invoice)
{
$txnId = 0;
if (is_object($Invoice->getLinkedTxn()) && $Invoice->getLinkedTxn()->getTxnType() == 'Payment') {
$txnId = $Invoice->getLinkedTxn()->getTxnId();
}
print('Invoice # '.$Invoice->getDocNumber().' has a total of $'.$Invoice->getTotalAmt().' and Linked Payment ID: ' . $txnId . "\n");
}
There are 4 receiving methods. 1) delivery 2) pickup 3) mobile_topup 4) bank_deposit
if there are 2 mobile topups there I need only one. But, if there are 2 delivery methods then I need both f them. To achieve this, I have created this query:
$clause = "SELECT id FROM beneficiary_payment_info
GROUP BY IF(ben_payment_method='mobile_topup', '', ben_payment_method)";
But, the problem is, it's group by with delivery methods as well. I don't want that.
Right now, I have 2 mobile_topup, 2 delivery and bank deposit in database.
I need 1 mobile_topup, 2 delivery and 1 bank deposit.
I was just wondering that is it possible in this query or I need to do it in php?
EDIT
temporary, in php I have this solution. But, it doesn't look reliable.
$mobile_count = array();
for($i=0; $i<count($data); $i++){
if($data[$i]['ben_payment_method']=='mobile_topup'){
//unset($data[$i]);
array_push($mobile_count, $i);
}
}
if(count($mobile_count) > 1){
for($i=0; $i<count($mobile_count)-1; $i++){
unset($data[$mobile_count[$i]]);
}
}
$clause = "SELECT id FROM beneficiary_payment_info
GROUP BY IF(ben_payment_method='mobile_topup', ben_payment_method, id,)";
I have a form that has 7 different items. The user will be able to input quantity (unlimited) and the price will be set for each item (let's say for example, item 1 is $18, and item 2 is $20, etc.). What I have done with another form that's almost identical is this:
if(!empty($_POST[qty_item_1])) {
$total_1 = ($_POST[qty_item_1] * 18);
} else {
$total_1 = "0";
}
if(!empty($_POST[qty_item_2])) {
$total_2 = ($_POST[qty_item_2] * 20);
} else {
$total_2 = "0";
}
I would have a code block like those for each item. It seems to work fine but I feel like this is probably the hard way to do it but I'm having trouble figuring out what else I might do. Any suggestions?
Given your field names, you could do something like:
$totals = array();
for ($i = 1; $i <= 7; $i++) {
$total[$i] = isset($_POST["qty_item_{$i}"]) ? intval($_POST["qty_item_{$i}"]) : 0;
}
The other option is to simply name your fields qty_item[]. When PHP parses the submitted data, it'll convert all those qty_item fields into an array for you. You'd still need to post-process to make sure that they contain valid numbers and whatnot, thoguh.