Build a salon with postgres and bash not passing tests

Hey team,

Script is doing exactly what is shown on the example.txt file given, I even changed my echo statements to make the ‘verbal’ responses identical, as well as dumbing down the code a bit (I took some creative liberty in terms of menus on my first go, and I did keep some quality checks like entering an actual phone number or time), and nothing. I changed the utils.js file to have a 30 second timeout because I saw that was a potential solution but it’s still not passing the tests even though it’s executing properly. Code below.

#!/bin/bash

PSQL="psql -X --username=freecodecamp --dbname=salon --tuples-only -c"

echo -e "\n~~~~~ MY SALON ~~~~~\n\nWelcome to My Salon, how can I help you?\n"

DISPLAY_SERVICES() {
  echo "$1" | while read SERVICE_ID BAR SERVICE_NAME
  do
    echo "$SERVICE_ID) $SERVICE_NAME"
  done
}

SERVICES_RESULT=$($PSQL "SELECT * FROM services")

DISPLAY_SERVICES "$SERVICES_RESULT"

read SERVICE_ID_SELECTED

SERVICE_NAME_RESULT=$($PSQL "SELECT name FROM services WHERE service_id=$SERVICE_ID_SELECTED")

while [[ -z $SERVICE_NAME_RESULT ]];
do
  echo -e "\nI could not find that service. What would you like today?"
  DISPLAY_SERVICES "$SERVICES_RESULT"
  read SERVICE_ID_SELECTED
  SERVICE_NAME_RESULT=$($PSQL "SELECT name FROM services WHERE service_id=$SERVICE_ID_SELECTED")
done

echo -e "\nWhat's your phone number?"
read CUSTOMER_PHONE

while [[ ! $CUSTOMER_PHONE =~ ^[1-9][0-9]{2}-[0-9]{3}-[0-9]{4}$ ]]
do
  echo "That is not a valid phone number. Please try again."
  read CUSTOMER_PHONE
done

CUSTOMER_NAME=$($PSQL "SELECT name FROM customers WHERE phone='$CUSTOMER_PHONE'")

if [[ -z $CUSTOMER_NAME ]];
then
  echo -e "\nI don't have a record for that phone number, what's your name?"
  read CUSTOMER_NAME
  INSERT_CUSTOMER_RESULT=$($PSQL "INSERT INTO customers(phone,name) VALUES('$CUSTOMER_PHONE','$CUSTOMER_NAME')")
fi

echo -e "\nWhat time would you like your $SERVICE_NAME_RESULT, $CUSTOMER_NAME?" | sed 's/  / /g'
read SERVICE_TIME

while [[ ! $SERVICE_TIME =~ ^([1-9]|1[0-2]):[0-5][0-9]$|^([1-9]|1[0-2])([ap]m)$ ]]
do
  echo -e "That doesn't look to be a valid time. Please try again."
  read SERVICE_TIME
done

CUSTOMER_ID=$($PSQL "SELECT customer_id FROM customers WHERE phone='$CUSTOMER_PHONE'")
INSERT_SERVICE_TIME_RESULT=$($PSQL "INSERT INTO appointments(customer_id, service_id, time) VALUES($CUSTOMER_ID,$SERVICE_ID_SELECTED,'$SERVICE_TIME')")
echo -e "\nI have put you down for a $SERVICE_NAME_RESULT at $SERVICE_TIME, $CUSTOMER_NAME." | sed 's/  / /g'

Any ideas please?

Hey, this is essentially a crosspost from my original post in the Backend Development forum that hasn’t gotten any responses.

Script is doing exactly what is shown on the example.txt file given, I even changed my echo statements to make the ‘verbal’ responses identical, as well as dumbing down the code a bit (I took some creative liberty in terms of menus on my first go, and I did keep some quality checks like entering an actual phone number or time), and nothing. I changed the utils.js file to have a 30 second timeout because I saw that was a potential solution but it’s still not passing the tests even though it’s executing properly. Code below.

#!/bin/bash

PSQL="psql -X --username=freecodecamp --dbname=salon --tuples-only -c"

echo -e "\n~~~~~ MY SALON ~~~~~\n\nWelcome to My Salon, how can I help you?\n"

DISPLAY_SERVICES() {
  echo "$1" | while read SERVICE_ID BAR SERVICE_NAME
  do
    echo "$SERVICE_ID) $SERVICE_NAME"
  done
}

SERVICES_RESULT=$($PSQL "SELECT * FROM services")

DISPLAY_SERVICES "$SERVICES_RESULT"

read SERVICE_ID_SELECTED

SERVICE_NAME_RESULT=$($PSQL "SELECT name FROM services WHERE service_id=$SERVICE_ID_SELECTED")

while [[ -z $SERVICE_NAME_RESULT ]];
do
  echo -e "\nI could not find that service. What would you like today?"
  DISPLAY_SERVICES "$SERVICES_RESULT"
  read SERVICE_ID_SELECTED
  SERVICE_NAME_RESULT=$($PSQL "SELECT name FROM services WHERE service_id=$SERVICE_ID_SELECTED")
done

echo -e "\nWhat's your phone number?"
read CUSTOMER_PHONE

while [[ ! $CUSTOMER_PHONE =~ ^[1-9][0-9]{2}-[0-9]{3}-[0-9]{4}$ ]]
do
  echo "That is not a valid phone number. Please try again."
  read CUSTOMER_PHONE
done

CUSTOMER_NAME=$($PSQL "SELECT name FROM customers WHERE phone='$CUSTOMER_PHONE'")

if [[ -z $CUSTOMER_NAME ]];
then
  echo -e "\nI don't have a record for that phone number, what's your name?"
  read CUSTOMER_NAME
  INSERT_CUSTOMER_RESULT=$($PSQL "INSERT INTO customers(phone,name) VALUES('$CUSTOMER_PHONE','$CUSTOMER_NAME')")
fi

echo -e "\nWhat time would you like your $SERVICE_NAME_RESULT, $CUSTOMER_NAME?" | sed 's/  / /g'
read SERVICE_TIME

while [[ ! $SERVICE_TIME =~ ^([1-9]|1[0-2]):[0-5][0-9]$|^([1-9]|1[0-2])([ap]m)$ ]]
do
  echo -e "That doesn't look to be a valid time. Please try again."
  read SERVICE_TIME
done

CUSTOMER_ID=$($PSQL "SELECT customer_id FROM customers WHERE phone='$CUSTOMER_PHONE'")
INSERT_SERVICE_TIME_RESULT=$($PSQL "INSERT INTO appointments(customer_id, service_id, time) VALUES($CUSTOMER_ID,$SERVICE_ID_SELECTED,'$SERVICE_TIME')")
echo -e "\nI have put you down for a $SERVICE_NAME_RESULT at $SERVICE_TIME, $CUSTOMER_NAME." | sed 's/  / /g'

Any ideas? I don’t want to waste my gitpod time clicking Run a thousand times. I have the files but can’t upload the github link without the tests passing.

a common issue with this project is the size of the time field. Make sure it is var char 10.

Made the change and didn’t work with a 30 second timeout.

do you know how to record your testing? (your own testing and not the test)
One thing to do is run thru some common scenarios with the program and record everything to a file. Then compare that file with the expected responses.
You can capture the response by just selecting everything on the screen and pasting it in to a file. Or you can use something like <script-command> | tee output.log to do that, where the <script-command> is whatever command runs your script.

How will that help? It’s running properly according to the required specs

It will allow us to confirm what you are saying. Just a thought.

Here’s some output, maybe I’m biased but it looks right to me. Tests still aren’t passing.


~~~~~ MY SALON ~~~~~

Welcome to My Salon, how can I help you?

1) hair cut
2) beard trim
3) hair dye

What's your phone number?

I don't have a record for that phone number, what's your name?

What time would you like your hair cut, Fabio?

I have put you down for a hair cut at 10:30, Fabio.

~~~~~ MY SALON ~~~~~

Welcome to My Salon, how can I help you?

1) hair cut
2) beard trim
3) hair dye

What's your phone number?

What time would you like your beard trim, Fabio?

I have put you down for a beard trim at 11am, Fabio.

~~~~~ MY SALON ~~~~~

Welcome to My Salon, how can I help you?

1) hair cut
2) beard trim
3) hair dye

I could not find that service. What would you like today?
1) hair cut
2) beard trim
3) hair dye

I could not find that service. What would you like today?
1) hair cut
2) beard trim
3) hair dye

What's your phone number?

I don't have a record for that phone number, what's your name?

What time would you like your hair dye, Jimbo?

I have put you down for a hair dye at 2pm, Jimbo.

Here’s what the tables look like also.

salon=> SELECT * FROM customers;
 customer_id |    phone     | name  
-------------+--------------+-------
          17 | 555-555-5555 | Fabio
          18 | 568-894-9845 | Jimbo
(2 rows)

salon=> SELECT * FROM appointments;
 appointment_id | customer_id | service_id | time  
----------------+-------------+------------+-------
             25 |          17 |          1 | 10:30
             26 |          17 |          2 | 11am
             27 |          18 |          3 | 2pm
(3 rows)

salon=> SELECT * FROM services;
 service_id |    name    
------------+------------
          1 | hair cut
          2 | beard trim
          3 | hair dye
(3 rows)

how come I can’t see any of the inputs you made in the output you captured?

try removing any checks like this one that were not explicitly requested also. Just do the bare minimum according to the requirements given in terms of error checking. ( so the phone validity check would be removed too for eg)

also instead of doing 2 selects into the customers table to get the name here and then the id elsewhere, I would just get both in one select to save time.

I looked at the documentation for tee but from what I read there was no way to capture the input, just the output from the script. I ran the command you posted just with -a to append everything to the output log. Is there a way to capture the terminal inputs?

sorry it’s been a while since I used it. It should be something like:
command 2>&1 | tee both-output.txt

Thanks for the suggestion but that command didn’t want to capture inputs, I found a way to do it using script -a -c "./salon.sh" both-output.log. Granted it wasn’t as cool as using tee because the responses didn’t record to the log file in real time but it seems to have worked. Also, thank you for the suggestions because with the removal of the phone number and time quality checks, every test is now passing except for 2, and now I’m super confused. The following 2 tests don’t pass:

You can create a row in the appointments table by running your script and entering 1, 555-555-5555, Fabio, 10:30 at each request for input if that phone number isn’t in the customers table. The row should have the customer_id for that customer, and the service_id for the service entered

You can create another row in the appointments table by running your script and entering 2, 555-555-5555, 11am at each request for input if that phone number is already in the customers table. The row should have the customer_id for that customer, and the service_id for the service entered

Below is a log file with the inputs to and outputs of the script:

Script started on 2024-09-14 22:20:13+00:00 [TERM="xterm-256color" TTY="/dev/pts/2" COLUMNS="135" LINES="39"]

~~~~~ MY SALON ~~~~~

Welcome to My Salon, how can I help you?

1) hair cut
2) beard trim
3) hair dye
1

What's your phone number?
555-555-5555

I don't have a record for that phone number, what's your name?
Fabio

What time would you like your hair cut, Fabio?
10:30

I have put you down for a hair cut at 10:30, Fabio.

Script done on 2024-09-14 22:20:23+00:00 [COMMAND_EXIT_CODE="0"]
Script started on 2024-09-14 22:20:48+00:00 [TERM="xterm-256color" TTY="/dev/pts/2" COLUMNS="135" LINES="39"]

~~~~~ MY SALON ~~~~~

Welcome to My Salon, how can I help you?

1) hair cut
2) beard trim
3) hair dye
10

I could not find that service. What would you like today?
1) hair cut
2) beard trim
3) hair dye
2

What's your phone number?
555-555-5555

What time would you like your beard trim, Fabio?
11am

I have put you down for a beard trim at 11am, Fabio.

Script done on 2024-09-14 22:21:02+00:00 [COMMAND_EXIT_CODE="0"]
Script started on 2024-09-14 22:21:25+00:00 [TERM="xterm-256color" TTY="/dev/pts/2" COLUMNS="135" LINES="39"]

~~~~~ MY SALON ~~~~~

Welcome to My Salon, how can I help you?

1) hair cut
2) beard trim
3) hair dye
3

What's your phone number?
987-987-9876

I don't have a record for that phone number, what's your name?
Jimbo

What time would you like your hair dye, Jimbo?
3pm

I have put you down for a hair dye at 3pm, Jimbo.

Script done on 2024-09-14 22:21:40+00:00 [COMMAND_EXIT_CODE="0"]

The tables look like this after:

salon=> SELECT * FROM appointments;
 appointment_id | customer_id | service_id | time  
----------------+-------------+------------+-------
             25 |         128 |          1 | 10:30
             26 |         128 |          2 | 11am
             27 |         129 |          3 | 3pm
(3 rows)

salon=> SELECT * FROM customers;
 customer_id |    phone     | name  
-------------+--------------+-------
         128 | 555-555-5555 | Fabio
         129 | 987-987-9876 | Jimbo
(2 rows)

Still looks right to me?

can you show me your table definitions?

I removed the phone number and time quality checks, my script now looks like this:

#!/bin/bash

PSQL="psql -X --username=freecodecamp --dbname=salon --tuples-only -c"

echo -e "\n~~~~~ MY SALON ~~~~~\n\nWelcome to My Salon, how can I help you?\n"

DISPLAY_SERVICES() {
  echo "$1" | while read SERVICE_ID BAR SERVICE_NAME
  do
    echo "$SERVICE_ID) $SERVICE_NAME"
  done
}

SERVICES_RESULT=$($PSQL "SELECT * FROM services")

DISPLAY_SERVICES "$SERVICES_RESULT"

read SERVICE_ID_SELECTED

SERVICE_NAME_RESULT=$($PSQL "SELECT name FROM services WHERE service_id=$SERVICE_ID_SELECTED")

while [[ -z $SERVICE_NAME_RESULT ]];
do
  echo -e "\nI could not find that service. What would you like today?"
  DISPLAY_SERVICES "$SERVICES_RESULT"
  read SERVICE_ID_SELECTED
  SERVICE_NAME_RESULT=$($PSQL "SELECT name FROM services WHERE service_id=$SERVICE_ID_SELECTED")
done

echo -e "\nWhat's your phone number?"
read CUSTOMER_PHONE

CUSTOMER_NAME=$($PSQL "SELECT name FROM customers WHERE phone='$CUSTOMER_PHONE'")

if [[ -z $CUSTOMER_NAME ]];
then
  echo -e "\nI don't have a record for that phone number, what's your name?"
  read CUSTOMER_NAME
  INSERT_CUSTOMER_RESULT=$($PSQL "INSERT INTO customers(phone,name) VALUES('$CUSTOMER_PHONE','$CUSTOMER_NAME')")
fi

echo -e "\nWhat time would you like your $SERVICE_NAME_RESULT, $CUSTOMER_NAME?" | sed 's/  / /g'
read SERVICE_TIME

CUSTOMER_ID=$($PSQL "SELECT customer_id FROM customers WHERE phone='$CUSTOMER_PHONE'")
INSERT_SERVICE_TIME_RESULT=$($PSQL "INSERT INTO appointments(customer_id, service_id, time) VALUES($CUSTOMER_ID,$SERVICE_ID_SELECTED,'$SERVICE_TIME')")

echo -e "\nI have put you down for a $SERVICE_NAME_RESULT at $SERVICE_TIME, $CUSTOMER_NAME." | sed 's/  / /g'

Table definitions are:

salon=> \d services;
                                         Table "public.services"
   Column   |         Type          | Collation | Nullable |                   Default                    
------------+-----------------------+-----------+----------+----------------------------------------------
 service_id | integer               |           | not null | nextval('services_service_id_seq'::regclass)
 name       | character varying(50) |           | not null | 
Indexes:
    "services_pkey" PRIMARY KEY, btree (service_id)
Referenced by:
    TABLE "appointments" CONSTRAINT "appointments_service_id_fkey" FOREIGN KEY (service_id) REFERENCES services(service_id)

salon=> \d appointments
                                             Table "public.appointments"
     Column     |         Type         | Collation | Nullable |                       Default                        
----------------+----------------------+-----------+----------+------------------------------------------------------
 appointment_id | integer              |           | not null | nextval('appointments_appointment_id_seq'::regclass)
 customer_id    | integer              |           |          | 
 service_id     | integer              |           |          | 
 time           | character varying(5) |           | not null | 
Indexes:
    "appointments_pkey" PRIMARY KEY, btree (appointment_id)
Foreign-key constraints:
    "appointments_customer_id_fkey" FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
    "appointments_service_id_fkey" FOREIGN KEY (service_id) REFERENCES services(service_id)

salon=> \d customers;
                                          Table "public.customers"
   Column    |         Type          | Collation | Nullable |                    Default                     
-------------+-----------------------+-----------+----------+------------------------------------------------
 customer_id | integer               |           | not null | nextval('customers_customer_id_seq'::regclass)
 phone       | character varying(12) |           | not null | 
 name        | character varying(40) |           | not null | 
Indexes:
    "customers_pkey" PRIMARY KEY, btree (customer_id)
    "customers_phone_key" UNIQUE CONSTRAINT, btree (phone)
Referenced by:
    TABLE "appointments" CONSTRAINT "appointments_customer_id_fkey" FOREIGN KEY (customer_id) REFERENCES customers(customer_id)

can you change this to var char 10 please?

That worked LOL

Why did that work?

https://forum.freecodecamp.org/t/relational-databases-salon-appointment-scheduler/710024/2?u=hbar1st

Sadly it was my very first suggestion. (but you had other issues to fix i guess).

The test has larger time fields.

Understood. Well thank you so much for your help, I really appreciate it. I couldn’t have gotten the tests to pass without you :slight_smile:

1 Like