Work to invoice

This commit is contained in:
Kevin Adametz 2021-02-10 10:42:24 +01:00
parent 224bf9e951
commit 02e78e7255
101 changed files with 23483 additions and 154 deletions

View file

@ -0,0 +1,66 @@
<?php
namespace App\Http\Controllers;
use App\Services\Invoice;
use Response;
use Storage;
class FileController extends Controller
{
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
}
public function show($id = null, $disk = null, $do='file')
{
$path = "";
$filename = "";
if($disk === 'user'){
$file = \App\Models\File::findOrFail($id);
$path = Storage::disk($disk)->path($file->dir.$file->filename);
if (file_exists($path)) {
return Response::file($path);
}
}
if ($disk === 'invoice'){
$shopping_order = \App\Models\ShoppingOrder::findOrFail($id);
$filename = Invoice::getFilename($shopping_order);
$path = Invoice::getDownloadPath($shopping_order);
if (!Storage::disk('public')->exists($path)) {
return Response::make('File no found.', 404);
}
$file = Storage::disk('public')->get($path);
$type = Storage::disk('public')->mimeType($path);
if($do === 'download'){
return Response::make($file, 200)
->header("Content-Type", $type)
->header('Content-disposition', 'attachment; filename="'.$filename.'"');
/* $full_path = Invoice::getDownloadPath($shopping_order, true);
$he
if (file_exists($full_path)) {
return Response::download($full_path, $filename);
}*/
}
if($do === 'stream'){
return Response::make($file, 200)
->header("Content-Type", $type)
->header('Content-disposition','filename="'.$filename.'"');
}
}
}
}

View file

@ -158,8 +158,6 @@ class LeadController extends Controller
if(isset($data['m_account']) && $data['m_account']){
$user = User::findOrFail($data['user_id']);
$rules['m_account'] = 'unique:user_accounts,m_account,'.$user->account->id.',id';
}
$validator = Validator::make(Request::all(), $rules);
if ($validator->fails()) {
@ -363,6 +361,9 @@ class LeadController extends Controller
->addColumn('first_name', function (User $user) {
return $user->account ? $user->account->first_name : '';
})
->addColumn('company', function (User $user) {
return $user->account ? $user->account->company : '';
})
->addColumn('last_name', function (User $user) {
return $user->account ? $user->account->last_name : '';
})
@ -400,8 +401,6 @@ class LeadController extends Controller
return "-";
})
->orderColumn('id', 'id $1')
->orderColumn('confirmed', 'confirmed $1')
->orderColumn('active', 'active $1')

View file

@ -7,6 +7,7 @@ use App\Models\ShoppingOrder;
use App\Models\ShoppingPayment;
use App\Models\ShoppingUser;
use App\Models\UserShop;
use App\Repositories\InvoiceRepository;
use App\Services\CustomerPriority;
use App\Services\Payment;
use Request;
@ -302,10 +303,26 @@ class SalesController extends Controller
}
if(isset($data['back'])){
return redirect($data['back']);
}
return back();
}
public function invoice(){
$data = Request::all();
//$data['id'] ShoppingOrder id
if(!isset($data['id'])){
abort(404);
}
if(isset($data['action'])){
if($data['action'] === 'create_invoice'){
$shopping_order = ShoppingOrder::findOrFail($data['id']);
$invoice_repo = new InvoiceRepository($shopping_order);
$invoice_repo->create($data);
return redirect(route('admin_sales_users_detail', [$shopping_order->id]));
}
}
}
}

View file

@ -2,21 +2,22 @@
namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use Auth;
use Yard;
use Request;
use App\User;
use Validator;
use App\Services\Util;
use App\Models\Product;
use App\Models\ShippingCountry;
use App\Models\ShoppingInstance;
use App\Models\ShoppingOrder;
use App\Models\ShoppingUser;
use App\Models\UserHistory;
use App\Models\UserShop;
use App\Services\Payment;
use App\Services\Util;
use App\User;
use Auth;
use Request;
use Validator;
use Yard;
use App\Models\UserHistory;
use App\Models\ShoppingUser;
use App\Models\ShoppingOrder;
use App\Models\ProductCategory;
use App\Models\ShippingCountry;
use App\Models\ShoppingInstance;
use App\Http\Controllers\Controller;
class OrderController extends Controller
@ -278,12 +279,8 @@ class OrderController extends Controller
public function datatable(){
$show_at = 1;
// $user = User::find(\Auth::user()->id);
;
if(Request::get('shipping_is_for') === 'me'){
$query = Product::select('products.*')->where('active', true)->where(function ($q) {
$query = Product::with('categories')->select('products.*')->where('active', true)->where(function ($q) {
$q->where('show_at', '=', 1)
->orWhere('show_at', '=', 2)
->orWhere('show_at', '=', 6);
@ -291,14 +288,11 @@ class OrderController extends Controller
});
}else{
$query = Product::select('products.*')->where('active', true)->where(function ($q) {
$query = Product::with('categories')->select('products.*')->where('active', true)->where(function ($q) {
$q->where('show_at', '=', 0)
->orWhere('show_at', '=', 1);
});
}
//Kunden und Vertriebspartner
//->orWhere('show_at', '=', 2); // Nur Vertriebspartner
//->orderBy('pos', 'DESC')
@ -347,21 +341,32 @@ class OrderController extends Controller
</div>';
})*/
->addColumn('category', function (Product $product) {
$ret = "";
foreach($product->categories as $category){
$ret .= '<span><div style="white-space: nowrap">'.$category->category->name.'</div></span>';
}
return $ret;
})
->addColumn('picture', function (Product $product) {
if(count($product->images)){
return '<img class="img-fluid img-extra" alt="" src="'.route('product_image', [$product->images->first()->slug]).'">';
return '<a href="" class="" data-modal="modal-lg" data-toggle="modal" data-target="#modals-load-content" data-id="'.$product->id.'" data-route="'.route('modal_load').'"
data-action="user-order-show-product" data-view="customer">
<img class="img-fluid img-extra" alt="" src="'.route('product_image', [$product->images->first()->slug]).'">
<div class="text-center"><i class="ion ion-md-eye"></i></div></a>';
}
return "";
})
->addColumn('price_net', function (Product $product) {
return $product->getFormattedPriceWith(true, true). "";
return $product->getFormattedPriceWith(true, true). "";
})
->addColumn('price_gross', function (Product $product) {
return $product->getFormattedPriceWith(false, true). " ";
return $product->getFormattedPriceWith(false, true). "";
})
->addColumn('price_vk_gross', function (Product $product) {
return $product->getFormattedPriceWith(false, false). " ";
return $product->getFormattedPriceWith(false, false). "";
})
->addColumn('single_commission', function (Product $product) {
return $product->single_commission ? '<span class="badge badge-warning">Handelspanne: '.$product->getFormattedValueCommission().' %</span>' : '<span class="badge badge-primary">Staffelprovision</span> <button class="btn btn-default btn-xs icon-btn md-btn-flat product-tooltip" title="details" data-modal="modal-lg"
@ -390,8 +395,21 @@ class OrderController extends Controller
->orderColumn('contents_total', 'contents_total $1')
->orderColumn('single_commission', 'single_commission $1')
->orderColumn('weight', 'weight $1')
// ->orderColumn('category', 'weight $1')
/*->orderColumn('category', function ($query, $order) {
$query->whereHas('categories',
function ($q) use ($order) {
// $q->select('sent_at')->where('sent_at', DB::raw("(select max('sent_at') customer_mails)")); //)
})->orderBy(
ProductCategory::select('id')
->whereColumn('product_id', 'produkt.id')
->orderBy('id', 'DESC')
->limit(1)
, $order);
})*/
->rawColumns(['add_card', 'product', 'quantity', 'picture', 'action', 'single_commission'])
->rawColumns(['add_card', 'category', 'product', 'quantity', 'picture', 'action', 'single_commission'])
->make(true);
}

View file

@ -7,6 +7,7 @@ use App\User;
use Auth;
use Request;
use Validator;
use App\Models\UserAccount;
class UserDataController extends Controller
@ -47,6 +48,14 @@ class UserDataController extends Controller
'address'=>'required',
'zipcode'=>'required',
'city' => 'required',
'phone' => 'required_without:mobil',
'mobil' => 'required_without:phone',
'tax_number' => 'required_without:tax_identification_number',
'tax_identification_number' => 'required_without:tax_number',
'birthday_day' => 'required',
'birthday_month' => 'required',
'birthday_year' => 'required',
'country_id' => 'required|integer|min:1',
'email' => 'required|string|email|max:255|exists:users,email',
'email-confirm' => 'required|same:email',
);
@ -67,7 +76,6 @@ class UserDataController extends Controller
$validator = Validator::make(Request::all(), $rules);
if ($validator->fails()) {
return view('user.edit', $data)->withErrors($validator);
} else {

View file

@ -194,9 +194,13 @@ class WizardController extends Controller
'city' => 'required',
'phone' => 'required_without:mobil',
'mobil' => 'required_without:phone',
'tax_number' => 'required_without:tax_identification_number',
'tax_identification_number' => 'required_without:tax_number',
'country_id' => 'required|integer|min:1',
'birthday' => 'required',
);
'birthday_day' => 'required',
'birthday_month' => 'required',
'birthday_year' => 'required'
);
if (!Request::get('same_as_billing')) {
$rules = array_merge($rules, [
@ -397,8 +401,12 @@ class WizardController extends Controller
'city' => 'required',
'phone' => 'required_without:mobil',
'mobil' => 'required_without:phone',
'tax_number' => 'required_without:tax_identification_number',
'tax_identification_number' => 'required_without:tax_number',
'country_id' => 'required|integer|min:1',
'birthday' => 'required',
'birthday_day' => 'required',
'birthday_month' => 'required',
'birthday_year' => 'required'
);
if(!Request::get('same_as_billing')){

View file

@ -44,6 +44,8 @@ use Illuminate\Database\Eloquent\Model;
* @method static \Illuminate\Database\Eloquent\Builder|Setting whereType($value)
* @method static \Illuminate\Database\Eloquent\Builder|Setting whereUpdatedAt($value)
* @mixin \Eloquent
* @property int|null $int
* @method static \Illuminate\Database\Eloquent\Builder|Setting whereInt($value)
*/
class Setting extends Model
{
@ -54,6 +56,7 @@ class Setting extends Model
protected $casts = [
'referenz' => 'int',
'status' => 'int',
'int' => 'int',
'object' => 'array'
];
@ -65,6 +68,7 @@ class Setting extends Model
'object',
'full_text',
'text',
'int',
'status',
'type'
];
@ -96,6 +100,9 @@ class Setting extends Model
case 'text':
return $content->text;
break;
case 'int':
return $content->int;
break;
}
}
return false;
@ -121,6 +128,9 @@ class Setting extends Model
case 'text':
$content->text = $value;
break;
case 'int':
$content->int = (int) $value;
break;
}
$content->save();

View file

@ -91,6 +91,8 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereDiscount($value)
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder wherePaymentCredit($value)
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereSubtotalShipping($value)
* @property string|null $total_without_credit
* @method static \Illuminate\Database\Eloquent\Builder|ShoppingOrder whereTotalWithoutCredit($value)
*/
class ShoppingOrder extends Model
{
@ -119,6 +121,7 @@ class ShoppingOrder extends Model
'points',
'weight',
'paid',
'invoice',
'txaction',
'wp_invoice_path',
'wp_notice',
@ -129,6 +132,7 @@ class ShoppingOrder extends Model
protected $casts = [
'wp_notice' => 'array',
'invoice' => 'array',
];
public static $shippedTypes = [

View file

@ -177,6 +177,9 @@ class UserAccount extends Model
return Carbon::parse($value)->format(\Util::formatDateDB());
}
public function getBirthdayRaw(){
return isset($this->attributes['birthday']) ? $this->attributes['birthday'] : NULL;
}
public function setBirthdayAttribute( $value ) {
$this->attributes['birthday'] = isset($value) ? (new Carbon($value))->format('Y-m-d') : NULL;
}

View file

@ -0,0 +1,63 @@
<?php
namespace App\Repositories;
use PDF;
use Storage;
use App\Models\ShoppingOrder;
use App\Services\Invoice;
use App\Services\MyPDFMerger;
class InvoiceRepository extends BaseRepository {
public function __construct(ShoppingOrder $model)
{
$this->model = $model;
}
public function create($request = [])
{
//need invoice $data
$invoice_number = isset($request['invoice_number']) ? $request['invoice_number'] : Invoice::getInvoiceNumber();
$invoice_date = isset($request['invoice_date']) ? $request['invoice_date'] : $this->model->created_at->format("d.m.Y");
$invoice_number = Invoice::createInvoiceNumber($invoice_number, $invoice_date);
$data = [
'shopping_order' => $this->model,
'invoice_date' => $invoice_date,
'invoice_number' => $invoice_number,
];
$pdf = PDF::loadView('pdf.invoice', $data);
$pdf->setPaper('A4', 'portrait');
$dir = Invoice::getInvoiceStorageDir($invoice_date);
if(!Storage::disk('public')->exists( $dir )){
Storage::disk('public')->makeDirectory($dir); //creates directory
}
$path = Storage::disk('public')->getAdapter()->getPathPrefix();
$filename = Invoice::makeInvoiceFilename($invoice_number);
$pdf->save($path.$dir.$filename);
$pdfMerger = new MyPDFMerger();
$pdfMerger->addPDF($path.$dir.$filename);
$file = $pdfMerger->myMerge('string', $filename, 'template_invoice_de');
Storage::disk('public')->put($dir.$filename, $file);
$data_file = [
'filename' => $filename,
'dir' => $dir,
'disk' => 'public',
'invoice_number' => $invoice_number,
'invoice_date' => $invoice_date,
];
$this->model->invoice = $data_file;
$this->model->save();
Invoice::makeNextInvoiceNumber();
return true;
//return $pdf->stream('invoice.pdf');
//return $this->output($path.$dir, $filename);
}
}

View file

@ -45,6 +45,11 @@ class UserRepository extends BaseRepository {
$data['same_as_billing'] = !isset($data['same_as_billing']) ? 0 : 1;
$data['birthday_day'] = isset($data['birthday_day']) ? $data['birthday_day'] : 1;
$data['birthday_month'] = isset($data['birthday_month']) ? $data['birthday_month'] : 1;
$data['birthday_year'] = isset($data['birthday_year']) ? $data['birthday_year'] : 1970;
$data['birthday'] = $data['birthday_day'].".".$data['birthday_month'].".".$data['birthday_year'];
$account->fill($data)->save();
if(!$this->model->account_id){

View file

@ -65,6 +65,39 @@ class HTMLHelper
}
public static function getCustomListOf($name, $select){
$ret = "";
if($name === 'day'){
$start = 1;
$end = 31;
$values = range($start, $end);
$ret = '<option value="">'.__('Tag').'</option>\n';
foreach ($values as $value){
$attr = ($value == $select) ? 'selected="selected"' : '';
$ret .= '<option value="'.$value.'" '.$attr.'>'.$value.'</option>\n';
}
}
if($name === 'month'){
$ret = '<option value="">'.__('Monat').'</option>\n';
foreach (self::$months as $key=>$value){
$attr = ($key == $select) ? 'selected="selected"' : '';
$ret .= '<option value="'.$key.'" '.$attr.'>'.$value.'</option>\n';
}
}
if($name === 'year'){
$start = date("Y", strtotime("-5 years", time()));
$end = date("Y", strtotime("-90 years", time()));
$values = range($start, $end);
$ret = '<option value="">'.__('Jahr').'</option>\n';
foreach ($values as $value){
$attr = ($value == $select) ? 'selected="selected"' : '';
$ret .= '<option value="'.$value.'" '.$attr.'>'.$value.'</option>\n';
}
}
return $ret;
}
public static function setContentReadMore($content){
$sep = '##mehr lesen##';

60
app/Services/Invoice.php Normal file
View file

@ -0,0 +1,60 @@
<?php
namespace App\Services;
use App\Services\Util;
use App\Models\Setting;
use App\Models\ShoppingOrder;
class Invoice
{
public static function getInvoiceNumber(){
return (int) Setting::getContentBySlug('invoice-number');
}
public static function makeNextInvoiceNumber(){
$invoice_number = self::getInvoiceNumber();
$invoice_number = $invoice_number+1;
Setting::setContentBySlug('invoice-number', $invoice_number, 'int');
return $invoice_number;
}
public static function createInvoiceNumber($invoice_number, $invoice_date){
$prefix = \Carbon::parse($invoice_date)->format('Ym');
return $prefix.$invoice_number;
}
public static function getInvoiceStorageDir($invoice_date){
return "/invoice/".\Carbon::parse($invoice_date)->format('Y/m/');
}
public static function makeInvoiceFilename($invoice_number){
return "Rechnung-".$invoice_number.".pdf";
}
public static function isInvoice(ShoppingOrder $shopping_order){
return isset($shopping_order->invoice['filename']) ? true : false;
}
public static function getFilename(ShoppingOrder $shopping_order){
return isset($shopping_order->invoice['filename']) ? $shopping_order->invoice['filename'] : false;
}
public static function getDir(ShoppingOrder $shopping_order){
return isset($shopping_order->invoice['dir']) ? $shopping_order->invoice['dir'] : false;
}
public static function getDownloadURL(ShoppingOrder $shopping_order, $do = false){
return route('storage_file', [$shopping_order->id, 'cms_download_file', $do]);
}
public static function getDownloadPath(ShoppingOrder $shopping_order, $full = false){
$dir = self::getDir($shopping_order);
$filename = self::getFilename($shopping_order);
if(!$full){
return $dir.$filename;
}
return \Storage::disk('public')->path($dir.$filename);
}
}

View file

@ -0,0 +1,188 @@
<?php
namespace App\Services;
//use FPDI in myMerge v2
//use FPDF;
//use FPDI;
class MyPDFMerger
{
private $_files; //['form.pdf'] ["1,2,4, 5-19"]
private $_fpdi;
public function __construct()
{
/* if(!class_exists("FPDF")) {
require_once(__DIR__.'/fpdf/fpdf.php');
}
if(!class_exists("FPDI")) {
require_once(__DIR__.'/fpdi/fpdi.php');
}*/
}
public function addPDF($filepath, $pages = 'all')
{
if (file_exists($filepath)) {
if (strtolower($pages) != 'all') {
$pages = $this->_rewritepages($pages);
}
$this->_files[] = array($filepath, $pages);
} else {
throw new \exception("Could not locate PDF on '$filepath'");
}
return $this;
}
public function myMerge($outputmode = 'browser', $outputpath = 'newfile.pdf', $theme = false)
{
if (!isset($this->_files) || !is_array($this->_files)): throw new \exception("No PDFs to merge."); endif;
$fpdi = new \setasign\Fpdi\Fpdi();
$first = 1;
//
//merger operations
foreach ($this->_files as $file) {
$filename = $file[0];
$filepages = $file[1];
$count = $fpdi->setSourceFile($filename);
//add the pages
if ($filepages == 'all') {
for ($i = 1; $i <= $count; $i++) {
$count = $fpdi->setSourceFile($filename);
$template = $fpdi->importPage($i);
$size = $fpdi->getTemplateSize($template);
$orientation = ($size['height'] > $size['width']) ? 'P' : 'L';
$fpdi->AddPage($orientation, array($size['width'], $size['height']));
if($theme){
$fpdi->setSourceFile('pdf/'.$theme.'-'.$first.'.pdf');
if($first == 1){
$first = 2;
}
$backId = $fpdi->importPage(1);
$fpdi->useTemplate($backId);
}
$fpdi->useTemplate($template);
}
} else {
foreach ($filepages as $page) {
$count = $fpdi->setSourceFile($filename);
if (!$template = $fpdi->importPage($page)): throw new \exception("Could not load page '$page' in PDF '$filename'. Check that the page exists."); endif;
$size = $fpdi->getTemplateSize($template);
$orientation = ($size['h'] > $size['w']) ? 'P' : 'L';
$fpdi->AddPage($orientation, array($size['w'], $size['h']));
if($theme){
$fpdi->setSourceFile('pdf/'.$theme.'-'.$first.'.pdf');
if($first == 1){
$first = 2;
}
$backId = $fpdi->importPage(1);
$fpdi->useTemplate($backId);
}
$fpdi->useTemplate($template);
}
}
//after first file (invoice) on bpaper
$slug = false;
}
//output operations
$mode = $this->_switchmode($outputmode);
if ($mode == 'S') {
return $fpdi->Output($outputpath, 'S');
} else {
if ($fpdi->Output($outputpath, $mode) == '') {
return true;
} else {
throw new \exception("Error outputting PDF to '$outputmode'.");
return false;
}
}
}
/**
* FPDI uses single characters for specifying the output location. Change our more descriptive string into proper format.
* @param $mode
* @return Character
*/
private function _switchmode($mode)
{
switch (strtolower($mode)) {
case 'download':
return 'D';
break;
case 'browser':
return 'I';
break;
case 'file':
return 'F';
break;
case 'string':
return 'S';
break;
default:
return 'I';
break;
}
}
/**
* Takes our provided pages in the form of 1,3,4,16-50 and creates an array of all pages
* @param $pages
* @return array
* @throws exception
*/
private function _rewritepages($pages)
{
$pages = str_replace(' ', '', $pages);
$part = explode(',', $pages);
//parse hyphens
foreach ($part as $i) {
$ind = explode('-', $i);
if (count($ind) == 2) {
$x = $ind[0]; //start page
$y = $ind[1]; //end page
if ($x > $y): throw new \exception("Starting page, '$x' is greater than ending page '$y'.");
return false; endif;
//add middle pages
while ($x <= $y): $newpages[] = (int)$x;
$x++; endwhile;
} else {
$newpages[] = (int)$ind[0];
}
}
return $newpages;
}
}
/*
$pdf = new PDFMerger;
$pdf->addPDF('samplepdfs/one.pdf', '1, 3, 4')
->addPDF('samplepdfs/two.pdf', '1-2')
->addPDF('samplepdfs/three.pdf', 'all')
->merge('file', 'samplepdfs/TEST2.pdf');
//REPLACE 'file' WITH 'browser', 'download', 'string', or 'file' for output options
//You do not need to give a file path for browser, string, or download - just the name.
*/

View file

@ -3,6 +3,7 @@ namespace App\Services;
use App\Mail\MailCheckout;
use App\Models\Setting;
use App\Models\ShoppingOrder;
use App\Models\ShoppingPayment;
use App\User;
@ -67,6 +68,11 @@ class Payment
}
return "warning";
}
public static function generateNextInvoiceNumber(){
$invoice_number = \App\Models\Setting::getContentBySlug('invoice-number');
return $invoice_number;
}
public static function getShoppingOrderBadge(ShoppingOrder $shopping_order){
if($shopping_order->mode === 'test'){

View file

@ -389,6 +389,13 @@ class User extends Authenticatable
return "de";
}
public function getBirthdayFormat($format = "d.m.Y"){
if($this->account && $this->account->getBirthdayRaw()){
return (int) Carbon::parse($this->account->getBirthdayRaw())->format($format);
}
return null;
}
/**
* Send the password reset notification.
*