Opencart extra field on payment select - opencart

I'm trying to add Automatic Incasso to the webshop. Everything is al done, but right now, i want to tweak it.
The online test website is: g7.rjbtest.nl
I want that if you choose the automatic incasso at step 5, at the bottom before the continue button an field is added where you have to put your bank account number in. Now that is on step 6, but that isn't user friendly.
The question is simple. Is it possible and if it is, how, to get an extra field where the user must put there bankaccount number, on the same step as where they select the automatic incasso.
Even if you can only point me in the right direction, i would be verry happy.
EDIT
Here's the code i've got in /catelog/controller/paymemt/incasso.php
<?php
class ControllerPaymentIncasso extends Controller {
protected function index() {
$this -> language -> load('payment/incasso');
$this -> data['text_instruction'] = $this -> language -> get('text_instruction');
$this -> data['text_description'] = $this -> language -> get('text_description');
$this -> data['text_payment'] = $this -> language -> get('text_payment');
$this -> data['text_number_insert'] = $this -> language -> get('text_number_insert');
$this -> data['bankNumberError'] = $this -> language -> get('bankNumberError');
$this -> data['button_confirm'] = $this -> language -> get('button_confirm');
$this -> data['bank'] = nl2br($this -> config -> get('incasso_bank_' . $this -> config -> get('config_language_id')));
$this -> data['continue'] = $this -> url -> link('checkout/success');
if (file_exists(DIR_TEMPLATE . $this -> config -> get('config_template') . '/template/payment/incasso.tpl')) {
$this -> template = $this -> config -> get('config_template') . '/template/payment/incasso.tpl';
} else {
$this -> template = 'default/template/payment/incasso.tpl';
}
$this -> render();
}
public function confirm() {
$this -> language -> load('payment/incasso');
$this -> load -> model('checkout/order');
$this -> load -> model('payment/incasso');
$comment = $this -> language -> get('text_instruction') . "\n\n";
$comment .= $this -> config -> get('incasso_bank_' . $this -> config -> get('config_language_id')) . "\n\n";
$comment .= $this -> language -> get('text_payment');
$this -> model_checkout_order -> confirm($this -> session -> data['order_id'], $this -> config -> get('incasso_order_status_id'), $comment, true);
$rekNum = $_GET['rn'];
$this -> model_payment_incasso -> insertRekNum($this -> session -> data['order_id'], $rekNum);
}
}
?>
And in catelog/model/payment/incasso.php
<?php
class ModelPaymentIncasso extends Model {
public function getMethod($address, $total) {
$this -> language -> load('payment/incasso');
$query = $this -> db -> query("SELECT * FROM " . DB_PREFIX . "zone_to_geo_zone WHERE geo_zone_id = '" . (int)$this -> config -> get('incasso_geo_zone_id') . "' AND country_id = '" . (int)$address['country_id'] . "' AND (zone_id = '" . (int)$address['zone_id'] . "' OR zone_id = '0')");
if ($this -> config -> get('incasso_total') > 0 && $this -> config -> get('incasso_total') > $total) {
$status = false;
} elseif (!$this -> config -> get('incasso_geo_zone_id')) {
$status = true;
} elseif ($query -> num_rows) {
$status = true;
} else {
$status = false;
}
$method_data = array();
if ($status) {
$method_data = array('code' => 'incasso', 'title' => $this -> language -> get('text_title'), 'sort_order' => $this -> config -> get('incasso_sort_order'));
}
return $method_data;
}
public function insertRekNum($orderNum, $rekNum) {
$sql = "INSERT INTO `" . DB_PREFIX . "order_incasso` (
`order_id` ,
`iban`
)
VALUES (
'$orderNum', '$rekNum'
);";
$this -> db -> query($sql);
}
}
?>
And in catelog/view/theme/default/template/payment/incasso.tpl
<h2><?php echo $text_instruction; ?></h2>
<div class="content">
<p><?php echo $text_description; ?></p>
<p><?php echo $bank; ?></p>
<p><?php echo $text_payment; ?></p>
</div>
<div class="buttons">
<div class="left" >
<?php echo $text_number_insert; ?> <input type="text" value="" id="bankAccountNumber" />
</div>
<div class="right">
<input type="button" value="<?php echo $button_confirm; ?>" id="button-confirm" class="button" />
</div>
</div>
<script type="text/javascript">
$('#button-confirm').bind('click', function() {
var bankNumber = $("#bankAccountNumber").val();
if(bankNumber.trim() == ""){
alert("<?php echo $bankNumberError; ?>");
return false;
}
$.ajax({
type: 'get',
url: 'index.php?route=payment/incasso/confirm&rn=' + bankNumber,
success: function() {
location = '<?php echo $continue; ?>';
}
});
});
</script>

The only thing that comes to mind is:
to update the payment.tpl template and add the bank account input here after the payment options are rendered
add a JS code that will immediately hide the input or make it not display by inline CSS (I prefer JS prior to inline CSS)
add JS code that will handle payment radios change event and when the Incasso payment option is checked, display the bank account input or hide it otherwise
add the JS code from Your incasso.tpl that will store the bank account to a DB...
This should be the simplest solution...

Related

Unit tests with Rocket.rs

Im trying to write some unit tests for the 3 routes of my Rocket app. So far the get index function works fine but the two post requests arent working
Im getting confused because i keep getting a 404 request and i don't really know why
tests.rs:
use super::rocket;
use rocket::local::blocking::Client;
use rocket::http::Status;
use rocket::uri;
#[test]
fn index() {
let client = Client::tracked(rocket()).expect("valid rocket instance");
let response = client.get(uri!(super::index)).dispatch();
assert_eq!(response.status(), Status::Ok);
}
#[test]
fn add() {
let client = Client::tracked(rocket()).expect("valid rocket instance");
let response = client.post(uri!(super::add))
.body("note=This is a test")
.dispatch();
assert_eq!(response.status(), Status::Ok);
}
#[test]
fn delete() {
let client = Client::tracked(rocket()).expect("valid rocket instance");
let response = client.post(uri!(super::delete))
.body("noteid=1")
.dispatch();
assert_eq!(response.status(), Status::Ok);
}
main.rs (some code omitted for space reasons):
#[cfg(test)] mod tests;
use curl::easy::{Easy, List};
use rocket::form::Form;
use rocket::response::content::RawHtml;
use rocket::response::Redirect;
use rocket::{response::content::RawCss, *};
use rocket_dyn_templates::tera;
use rusqlite::{Connection, Result};
use std::io::Read;
#[derive(FromForm)]
struct NoteForm {
note: String,
}
#[derive(Debug)]
struct Note {
id: i32,
note: String,
}
#[derive(FromForm)]
struct NoteID {
noteid: i32,
}
#[get("/")]
fn index() -> RawHtml<String> {
let mut html: String = r#"
<link rel="stylesheet" href="style.css">
<h1>Rust Notebook</h1>
<form method='POST' action='/add'>
<label>Note: <input name='note' value=''></label>
<button>Add</button>
</form>
<ul class='notes'>"#
.to_owned();
let notes = get_notes().unwrap();
for note in notes {
let noteid: String = note.id.to_string();
html += "<li class='notes'>";
html += &tera::escape_html(&note.note);
html += "<form method='POST' action='/delete'> <button name='noteid' value='";
html += &noteid;
html += "' style='float: right;'>Delete</button></form></li>";
}
html += "</ul>";
RawHtml(html)
}
#[post("/delete", data = "<noteid>")]
fn delete(noteid: Form<NoteID>) -> Redirect {
let conn = Connection::open("notes.db").unwrap();
conn.execute(
"DELETE FROM notes WHERE rowid = ?",
&[noteid.noteid.to_string().as_str()],
)
.unwrap();
Redirect::to("/")
}
#[post("/add", data = "<note>")]
fn add(note: Form<NoteForm>) -> Redirect {
let conn = Connection::open("notes.db").unwrap();
conn.execute("INSERT INTO notes (note) VALUES (?)", &[note.note.as_str()])
.unwrap();
log_notes(&note.note.as_str());
Redirect::to("/")
}
#[launch]
fn rocket() -> _ {
sqlite();
rocket::build().mount("/", routes![index, add, serve_css, delete])
}
any help would be great :)

Create an admin menu in Opencart 4

In Opencart4 I am creating a new module. Installed the module and working fine from accessing Admin-> extensions -> modules -> module name -> (then edit).
Now I would like to add a new menu item under the "Catalogue" menu in the admin part.
I have done the following
In module's controller I added
$this->load->model('setting/event');
$this->model_setting_event->deleteEventByCode('MY_EVENT');
$this->model_setting_event->addEvent('MY_EVENT', "",'admin/view/common/column_left/before', 'extension/testimonials/module/testimonials/ADDTOADMINMENU');
ADDTOADMINMENU function in the module's controller looks like
public function ADDTOADMINMENU(&$route, &$data){
/**
* Check if current logged in user has permission to access that link
* Replace "extension/module/MY_EXTENSION" with your target path
* This check can very well be ignored/deleted...
**/
echo "Here";
exit;
if ($this->user->hasPermission('access', 'extension/testimonials/module/testimonials')) {
$my_menu_entry = array(
'id' => 'menu-MY_EXTENSION',
'icon' => 'fa-check',
'name' => 'My menu entry',
'href' => $this->url->link('extension/testimonials/module/testimonials', 'user_token=' . $this->session->data['user_token'], true),
'children' => array()
);
$target_menu_id = 'menu-catalog';
$target_submenu_href = $this->url->link('catalog/product', 'user_token=' . $this->session->data['user_token'], true);
$new_menu = array();
foreach( $data['menus'] as &$menu ) {
if( $menu['id'] == $target_menu_id ) {
$new_submenu = array();
foreach( $menu['children'] as $submenu ) {
if( $submenu['href'] == $target_submenu_href ) {
$new_submenu[] = $my_menu_entry;
$new_submenu[] = $submenu;
} else {
$new_submenu[] = $submenu;
}
}
$menu['children'] = $new_submenu;
$new_menu[] = $menu;
} else {
$new_menu[] = $menu;
}
}
$data['menus'] = $new_menu;
}
}
But not even entering in this function. Is the correct way I am following ?
Please guide.
try this:
$this->model_setting_event->addEvent('MY_EVENT', "",'admin/view/common/column_left/before', 'extension/testimonials/module/testimonials/ADDTOADMINMENU');
replace with:
$this->model_setting_event->addEvent('MY_EVENT', "",'admin/view/common/column_left/before', 'extension/testimonials/module/testimonials|ADDTOADMINMENU');
I have not checked, but OC have changed they framework a bit.
Solution :
Replace
$this->model_setting_event->addEvent('MY_EVENT', "",'admin/view/common/column_left/before', 'extension/testimonials/module/testimonials/ADDTOADMINMENU');
With
$dataEvent = [
'code' => 'MY_EVENT',
'description' => '',
'trigger' => 'admin/view/common/column_left/before',
'action' => 'extension/testimonials/module/testimonials|ADDTOADMINMENU',
'status' => true,
'sort_order' => 0,
];
if (version_compare(VERSION, '4.0.1.0', '>=')) {
$this->model_setting_event->addEvent($dataEvent);
} elseif (version_compare(VERSION, '4.0.0.0', '>=')) {
$this->model_setting_event->addEvent($dataEvent['code'], $dataEvent['description'], $dataEvent['trigger'], $dataEvent['action'], $dataEvent['status'], $dataEvent['sort_order']);
}else {
/* compatibility Opencart 3 */
$dataEvent['trigger']=str_replace("|","/",$dataEvent['trigger']);
$this->model_setting_event->addEvent($dataEvent['code'], $dataEvent['trigger'], $dataEvent['action'], $dataEvent['status'], $dataEvent['sort_order']);
}
Now you can use your code to update also Admin menu on Opencart 3

Prestashop webservice add product's tags and attachment document

How I can add tags in a product using prestashop webservice api?
I need a a function in this way:
function addTagToProduct((int)$ProductId, (string)$tagname){}
The same for attachment document: what shall I pass to webservice for add those ?
I use this function for add tags to my product:
public function getTagId($Tag){
//if tag exists
$xml = $this->get(array('url' => $this->url . '/api/tags?filter[name]='.$Tag.'&limit=1'));
$resources = $xml -> children() -> children();
if(!empty($resources)){
$attributes = $resources->tag->attributes();
return $attributes['id'];
}
//if not exists, add it
$xml = $this->get(array('url' => $this->url . '/api/tags?schema=synopsis'));
$resources = $xml -> children() -> children();
unset($resources->id);
$resources->name = $Tag;
$resources->id_lang = $this->getIdLang();
$opt = array(
'resource' => 'tags',
'postXml' => $xml->asXML()
);
$xml = $this->add($opt);
return $xml->tag->id;
}
Hope it help.

CakePHP - Adding Form Validation based on Database Fields

I need to validate shipping information entered when goods are dispatched. (I am having a nightmare using Cake!)
Each shipping company has a different format for their tracking references. I have written some regex to validate, and these are stored in my database.
All the validation for CakePHP happens in the model so I cannot use $this to retrieve the correct regex.
The regex is available in the view; is there anyway to use this to validate before the form is submitted?
I am currently sending the data through an ajax call
Controller
public function editTracking() {
$this->autoRender = false;
if ($this->request->is('ajax')) {
if($this->GoodsOutNote->save($this->request->data['GoodsOutNote'])){
$this->GoodsOutNote->save($this->request->data['GoodsOutNote']);
print_r($this->request->data['GoodsOutNote']['tracking_details']);
}else{
print_r($errors = $this->GoodsOutNote->validationErrors);
}
}
}
View
<?php echo $this->Form->create('GoodsOutNote',array(
'action'=>'editTracking','default' => false)); ?>
<fieldset>
<?php
echo $this->Form->input('id',array(
'default'=>$goodsOutNote['GoodsOutNote']['id']));
echo $this->Form->input('tracking_details',array(
'default'=>$goodsOutNote['GoodsOutNote']['tracking_details']));
?>
</fieldset>
<?php echo $this->Form->end(__('Submit'));
$data = $this->Js->get('#GoodsOutNoteEditTrackingForm')->serializeForm(array(
'isForm' => true, 'inline' => true));
$this->Js->get('#GoodsOutNoteEditTrackingForm')->event('submit',
$this->Js->request(
array('action' => 'editTracking', 'controller' => 'goods_out_notes'),
array(
'update' => '#tracking_details,#GoodsOutNoteTrackingDetails',
'data' => $data,
'async' => true,
'dataExpression'=>true,
'method' => 'PUT'
)
)
);
echo $this->Js->writeBuffer();
?>
In the view, I can use $goodsOutNote['ShippingMethod']['valid_regex'] to access the correct format but I am lost as to how I can pass this to the form.
I have fixed this using the following approach.
In my controller, I retrieve the full record that I am about to edit. I can then validate the input using preg_match(). I would really appreciate any comments on this - is there a better approach?
public function editTracking() {
$this->autoRender = false;
if ($this->request->is('ajax')) {
$id = $this->request->data['GoodsOutNote']['id'];
$options = array('conditions' => array('GoodsOutNote.' . $this->GoodsOutNote->primaryKey => $id));
$goodsOutNote = $this->GoodsOutNote->find('first', $options);
$trackingRef = $this->request->data['GoodsOutNote']['tracking_details'];
$regex = "/".$goodsOutNote['ShippingMethod']['valid_regex']."/";
if(preg_match($trackingRef,$regex)){
if($this->GoodsOutNote->save($this->request->data['GoodsOutNote'])){
$this->GoodsOutNote->save($this->request->data['GoodsOutNote']);
print_r($trackingRef);
}
else{
print_r($errors = $this->GoodsOutNote->validationErrors);
}
}
else {
print_r($errors = $trackingRef.'is not valid');
}
}
}

Custom Twig tag; could not find base class __TwigTemplate_

I'm trying to create a custom Twig tag (http://twig.sensiolabs.org/doc/advanced.html#tags) for my custom website system.
By using the following tag in a template:
{% entity '\\Testimonial\\Entity\\Testimonial' with { 'limit' : 2, 'column' : 'created' } %}
The custom tag will load the last 2 Testimonials from the database ordered by the column created. Ok, so far so good.
For the TokenParser I used code from the include tag:
class Entity extends Twig_TokenParser
{
public function parse(Twig_Token $token)
{
$object = $this -> parser -> getCurrentToken() -> getValue();
if( empty($object))
{
return;
}
$expr = $this->parser->getExpressionParser()->parseExpression();
$variables = $this->parseArguments();
return new EntityNode( $object, $expr, $variables, $token->getLine(), $this->getTag() );
}
protected function parseArguments()
{
$stream = $this->parser->getStream();
$variables = null;
if ($stream->test(Twig_Token::NAME_TYPE, 'with')) {
$stream->next();
$variables = $this->parser->getExpressionParser()->parseExpression();
}
$stream->expect(Twig_Token::BLOCK_END_TYPE);
return $variables;
}
public function getTag()
{
return "entity";
}
}
And for the Node I've borrowed from include and some other examples I've found resulting in:
class EntityNode extends Twig_Node implements Twig_NodeOutputInterface
{
public function __construct(
$object,
Twig_Node_Expression $expr,
Twig_Node_Expression $variables = null,
$lineno,
$tag = null )
{
parent::__construct(array('expr' => $expr, 'variables' => $variables), array("object" => $object), $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
{
$compiler->addDebugInfo($this);
$obj = $this->getAttribute('object');
if( !is_callable( $obj ) || !class_exists( $obj ))
{
// error not callable
}
$entities = forward_static_call( array( $obj , "TemplateEntity" ) , $this -> getNode( "variables" ));
$subtemplate = forward_static_call( array( $obj , "TemplateEntityTemplatePath" ));
$template = new Twig_Node_Expression_Constant( $subtemplate , $this -> getLine() );
#return;
$compiler
-> write("\$this->env->loadTemplate(")
-> subcompile($template)
-> raw(")")
;
}
}
The result is an error from Twig saying it can't load the basetemplate:
Parse error: syntax error, unexpected 'echo' (T_ECHO) in /domains/<domain>/lib/framework/vendors/twig/lib/Twig/Environment.php(328) : eval()'d code on line 370
0 - Exception occurred
Exception -- Autoloader could not find base class __TwigTemplate_c56f3794ae5aed2d0cc25529303a838625ded364d30febb96cd025a5d7622121
I know everything works correctly until the Twig_Node, the problem lies in how Twig parses the line $compiler
-> write("\$this->env->loadTemplate(")
-> subcompile($template)
-> raw(")")
;
Hope to get some help from you guys; any help is appreciated!
So in the end Twig has a weird way of formulating errors in the code.
After careful considering other Node examples in the Twig node directory I noted the following missing ; at the end of the compiler method raw:
class EntityNode extends Twig_Node implements Twig_NodeOutputInterface
{
public function __construct(
$object,
Twig_Node_Expression $expr,
Twig_Node_Expression $variables = null,
$lineno,
$tag = null )
{
parent::__construct(array('expr' => $expr, 'variables' => $variables), array("object" => $object), $lineno, $tag);
}
public function compile(Twig_Compiler $compiler)
{
$compiler->addDebugInfo($this);
$obj = $this->getAttribute('object');
if( !is_callable( $obj ) || !class_exists( $obj ))
{
// error not callable
}
$entities = forward_static_call( array( $obj , "TemplateEntity" ) , $this -> getNode( "variables" ));
$subtemplate = forward_static_call( array( $obj , "TemplateEntityTemplatePath" ));
$template = new Twig_Node_Expression_Constant( $subtemplate , $this -> getLine() );
#return;
$compiler
-> write("\$this->env->loadTemplate(")
-> subcompile($template)
-> raw(");\n")
;
}
}